1use std::sync::Arc;
2use crate::{AutogradMetaT, Dim, Dims, Error, Layout, Result, Shape, Storage, WithDType, D};
3use crate::{Tensor, TensorId, TensorImpl, Slice};
4
5impl<T: WithDType> Tensor<T> {
6 pub fn squeeze<D: Dim>(&self, dim: D) -> Result<Self> {
16 let dims = self.dims();
17 let dim = dim.to_index(self.shape(), "squeeze")?;
18 if dims[dim] == 1 {
19 let mut dims = dims.to_vec();
20 let mut strides = self.layout().stride().to_vec();
21 dims.remove(dim);
22 strides.remove(dim);
23 let tensor_ = TensorImpl {
24 id: TensorId::new(),
25 storage: self.0.storage.clone(),
26 layout: Layout::new(dims, strides, self.layout().start_offset()),
27 meta: T::AutogradMeta::on_reshape_op(self)
28 };
29 Ok(Self(Arc::new(tensor_)))
30 } else {
31 Err( Error::SqueezeDimNot1 { shape: self.shape().clone(), dim } )?
32 }
33 }
34
35 pub fn unsqueeze<D: Dim>(&self, dim: D) -> Result<Self> {
48 let mut dims = self.dims().to_vec();
49 let mut strides = self.layout().stride().to_vec();
50 let dim = dim.to_index_plus_one(self.shape(), "unsqueeze")?;
51 dims.insert(dim, 1);
52 let stride = if dim < strides.len() { strides[dim] } else { 1 };
53 strides.insert(dim, stride);
54 let tensor_ = TensorImpl {
55 id: TensorId::new(),
56 storage: self.0.storage.clone(),
57 layout: Layout::new(dims, strides, self.layout().start_offset()),
58 meta: T::AutogradMeta::on_reshape_op(self),
59 };
60 Ok(Self(Arc::new(tensor_)))
61 }
62
63 pub fn narrow<D: Dim>(&self, dim: D, start: usize, len: usize) -> Result<Self> {
80 let dims = self.dims();
81 let dim = dim.to_index(self.shape(), "narrow")?;
82 let err = |msg| {
83 Err::<(), _>(Error::NarrowInvalidArgs {
84 shape: self.shape().clone(),
85 dim,
86 start,
87 len,
88 msg,
89 })
90 };
91
92 if start > dims[dim] {
93 err("start > dim_len")?;
94 }
95 if start.saturating_add(len) > dims[dim] {
96 err("start + len > dim_len")?
97 }
98 if start == 0 && dims[dim] == len {
99 Ok(self.clone())
100 } else {
101 let meta = T::AutogradMeta::on_narrow_op(self, dim, start, len);
102 let layout = self.layout().narrow(dim, start, len)?;
103 let tensor_ = TensorImpl {
104 id: TensorId::new(),
105 storage: self.0.storage.clone(),
106 layout,
107 meta
108 };
109 Ok(Self(Arc::new(tensor_)))
110 }
111 }
112
113 pub fn slice<D: Dim>(&self, dim: D, slice: &Slice) -> Result<Self> {
127 let dims = self.dims();
128 let dim = dim.to_index(self.shape(), "narrow")?;
129 let err = |msg| {
130 Err::<(), _>(Error::SliceInvalidArgs {
131 shape: self.shape().clone(),
132 dim,
133 slice: slice.clone(),
134 msg,
135 })
136 };
137
138 let end = match slice.end {
139 Some(end) if end >= 0 => end as usize,
140 Some(end) => {
141 let dis = -end as usize;
142 if dis > dims[dim] {
143 0
144 } else {
145 dims[dim] - dis
146 }
147 }
148 None => dims[dim],
149 };
150 if slice.start > dims[dim] {
151 err("start > dim_len")?;
152 }
153 if end > dims[dim] {
154 err("end > dim_len")?
155 }
156 if slice.start == 0 && dims[dim] == end && slice.step == 1 {
157 Ok(self.clone())
158 } else {
159 let meta = T::AutogradMeta::on_slice_op(self, dim, slice.start, end, slice.step);
160 let layout = self.layout().slice(dim, slice.start, end, slice.step)?;
161 Ok(self.share_storage(layout, meta))
162 }
163 }
164
165 pub fn reshape<S: ShapeWithHolder>(&self, shape: S) -> Result<Self> {
182 let shape = shape.into_shape(self.shape())?;
183 let meta = T::AutogradMeta::on_reshape_op(self);
184 if self.is_contiguous() {
185 let layout = Layout::contiguous_with_offset(shape, self.layout().start_offset());
186 Ok(self.share_storage(layout, meta))
187 } else {
188 let storage = self.storage_read()?.copy(self.layout());
189 Ok(Self::from_storage(storage, shape, meta))
190 }
191 }
192
193 pub fn transpose<D1: Dim, D2: Dim>(&self, dim1: D1, dim2: D2) -> Result<Self> {
195 let dim1 = dim1.to_index(self.shape(), "transpose")?;
196 let dim2 = dim2.to_index(self.shape(), "transpose")?;
197 if dim1 == dim2 {
198 return Ok(self.clone());
199 }
200
201 let meta = T::AutogradMeta::on_transpose_op(self, dim1, dim2);
202 let layout = self.layout().transpose(dim1, dim2)?;
203 Ok(self.share_storage(layout, meta))
204 }
205
206 pub fn transpose_last(&self) -> Result<Self> {
207 self.transpose(D::Minus1, D::Minus2)
208 }
209
210 pub fn permute<D: Dims>(&self, dims: D) -> Result<Self> {
221 let dims = dims.to_indexes(self.shape(), "permute")?;
222 let is_permutation =
224 dims.len() == self.rank() && (0..dims.len()).all(|i| dims.contains(&i));
225 if !is_permutation {
226 crate::bail!(
227 "dimension mismatch in permute, tensor {:?}, dims: {:?}",
228 self.dims(),
229 dims
230 )
231 }
232 let layout = self.layout().permute(&dims)?;
234 let meta = T::AutogradMeta::on_permute_op(self, dims);
235 Ok(self.share_storage(layout, meta))
236 }
237
238 pub fn cat<A: AsRef<Tensor<T>>, D: Dim>(arrs: &[A], dim: D) -> Result<Self> {
255 if arrs.is_empty() {
257 Err(Error::OpRequiresAtLeastOneTensor { op: "cat" })?
258 }
259
260 let arr0 = &arrs[0];
262 let rank0 = arr0.as_ref().rank();
263
264 let cat_dim = dim.to_index(arr0.as_ref().shape(), "cat")?;
266 let mut target_dims = arr0.as_ref().dims().to_vec();
267 target_dims[cat_dim] = 0;
268 let mut dim_offsets = vec![];
269
270 for (_arr_index, arr) in arrs.iter().enumerate() {
271 let rank = arr.as_ref().rank();
273 if rank != rank0 {
274 Err(Error::UnexpectedNumberOfDims {
275 expected: rank,
276 got: arr.as_ref().rank(),
277 shape: arr.as_ref().shape().clone(),
278 })?
279 }
280
281 for (dim_index, (v1, v2)) in arr0.as_ref().dims().iter()
283 .zip(arr.as_ref().dims().iter())
284 .enumerate()
285 {
286 if dim_index == cat_dim {
288 dim_offsets.push(target_dims[cat_dim]);
289 target_dims[cat_dim] += v2;
290 }
291
292 if dim_index != cat_dim && v1 != v2 {
294 Err(Error::ShapeMismatchCat {
295 dim: dim_index,
296 first_shape: arr0.as_ref().shape().clone(),
297 n: dim_index + 1,
298 nth_shape: arr0.as_ref().shape().clone(),
299 })?
300 }
301 }
302 }
303
304 let target_shape: Shape = target_dims.into();
309
310 let mut dst: Vec<T> = Vec::with_capacity(target_shape.element_count());
312 unsafe { dst.set_len(target_shape.element_count()) };
313
314 let meta = T::AutogradMeta::on_cat_op(arrs, cat_dim);
315 let res_arr = Self::from_storage(Storage::new(dst), target_shape, meta);
316
317 for (arr_index, arr) in arrs.iter().enumerate() {
318 let sub_res_arr = res_arr.narrow(cat_dim, dim_offsets[arr_index], arr.as_ref().dims()[cat_dim])?;
320 assert_eq!(sub_res_arr.shape(), arr.as_ref().shape());
321 sub_res_arr.impl_copy_(arr.as_ref())?;
322 }
323
324 Ok(res_arr)
325 }
326
327 pub fn stack<A: AsRef<Tensor<T>>, D: Dim>(args: &[A], dim: D) -> Result<Self> {
343 if args.is_empty() {
344 Err(Error::OpRequiresAtLeastOneTensor { op: "stack" })?
345 }
346 let dim = dim.to_index_plus_one(args[0].as_ref().shape(), "stack")?;
347 let args = args
348 .iter()
349 .map(|t| t.as_ref().unsqueeze(dim))
350 .collect::<Result<Vec<_>>>()?;
351 Self::cat(&args, dim)
352 }
353
354 pub fn split<D: Dim>(&self, dim: D) -> Result<Vec<Self>> {
387 let split_index = dim.to_index(self.shape(), "split")?;
388 let split_dim_size = self.dims()[split_index];
389 let mut splited_shape = self.dims().to_vec();
390 splited_shape.remove(split_index);
391
392 let mut vec = vec![];
393 for i in 0..split_dim_size {
394 let sub_tensor = self.narrow(split_index, i, 1)?.squeeze(split_index)?;
395 vec.push(sub_tensor);
396 }
397
398 Ok(vec)
399 }
400
401 pub fn chunk<D: Dim>(&self, chunks: usize, dim: D) -> Result<Vec<Self>> {
404 let dim = dim.to_index(self.shape(), "chunk")?;
405 let size = self.dim(dim)?;
406 if size < chunks {
407 (0..size).map(|i| self.narrow(dim, i, 1)).collect()
408 } else {
409 let chunk_size = size / chunks;
410 let cnt_additional = size % chunks;
411 let mut tensors = vec![];
412 let mut sum_chunk_size = 0;
413 for i in 0..chunks {
414 let chunk_size = if i < cnt_additional {
415 chunk_size + 1
416 } else {
417 chunk_size
418 };
419 let tensor = self.narrow(dim, sum_chunk_size, chunk_size)?;
420 tensors.push(tensor);
421 sum_chunk_size += chunk_size
422 }
423 Ok(tensors)
424 }
425 }
426
427 pub fn flatten<D1: Dim, D2: Dim>(&self, start_dim: D1, end_dim: D2) -> Result<Self> {
430 self.flatten_(Some(start_dim), Some(end_dim))
431 }
432
433 pub fn flatten_to<D: Dim>(&self, end_dim: D) -> Result<Self> {
435 self.flatten_(None::<usize>, Some(end_dim))
436 }
437
438 pub fn flatten_from<D: Dim>(&self, start_dim: D) -> Result<Self> {
441 self.flatten_(Some(start_dim), None::<usize>)
442 }
443
444 pub fn flatten_all(&self) -> Result<Self> {
455 self.flatten_(None::<usize>, None::<usize>)
456 }
457
458 pub fn repeat<S: Into<Shape>>(&self, shape: S) -> Result<Self> {
460 let repeats: Shape = shape.into();
461 let mut repeats = repeats.dims().to_vec();
462
463 if repeats.len() > self.rank() {
464 Err(Error::RepeatRankOutOfRange { repeats: repeats.clone().into(), shape: self.shape().into() })?;
465 } else if repeats.len() > self.rank() {
466 for _ in 0..(repeats.len() - self.rank()) {
467 repeats.push(1);
468 }
469 }
470
471 let mut arr = self.clone();
472
473 for (idx, &repeat) in repeats.iter().enumerate() {
474 if repeat > 1 {
475 arr = Tensor::cat(&vec![&arr; repeat], idx)?
476 }
477 }
478 Ok(arr)
479 }
480
481 pub fn repeat_dim<D: Dim>(&self, dim: D, times: usize) -> Result<Self> {
483 if times == 0 {
484 self.squeeze(dim)
485 } else if times == 1 {
486 Ok(self.clone())
487 } else {
488 Tensor::cat(&vec![self; times], dim)
489 }
490 }
491
492 fn flatten_<D1: Dim, D2: Dim>(
493 &self,
494 start_dim: Option<D1>,
495 end_dim: Option<D2>,
496 ) -> Result<Self> {
497 if self.rank() == 0 {
498 self.reshape(1)
499 } else {
500 let start_dim = match start_dim {
501 None => 0,
502 Some(dim) => dim.to_index(self.shape(), "flatten")?,
503 };
504 let end_dim = match end_dim {
505 None => self.rank() - 1,
506 Some(dim) => dim.to_index(self.shape(), "flatten")?,
507 };
508 if start_dim < end_dim {
509 let dims = self.dims();
510 let mut dst_dims = dims[..start_dim].to_vec();
511 dst_dims.push(dims[start_dim..end_dim + 1].iter().product::<usize>());
512 if end_dim + 1 < dims.len() {
513 dst_dims.extend(&dims[end_dim + 1..]);
514 }
515 self.reshape(dst_dims)
516 } else {
517 Ok(self.clone())
518 }
519 }
520 }
521}
522
523pub trait ShapeWithHolder {
524 fn into_shape(self, shape: &Shape) -> crate::Result<Shape>;
525}
526
527impl<S: Into<Shape>> ShapeWithHolder for S {
528 fn into_shape(self, origin_shape: &Shape) -> crate::Result<Shape> {
529 let shape = self.into();
530 if shape.element_count() != origin_shape.element_count() {
531 return Err(Error::ElementCountMismatchInReshape {
532 origin: origin_shape.clone(),
533 target: shape,
534 })?;
535 }
536 Ok(shape)
537 }
538}
539
540fn hole_size(shape: &Shape, prod_d: usize, s: &dyn std::fmt::Debug) -> Result<usize> {
541 let el_count = shape.element_count();
542 if prod_d == 0 {
543 crate::bail!("cannot reshape tensor of {el_count} elements to {s:?}")
544 }
545 if el_count % prod_d != 0 {
546 crate::bail!("cannot reshape tensor with {el_count} elements to {s:?}")
547 }
548 Ok(el_count / prod_d)
549}
550
551impl ShapeWithHolder for ((), usize) {
552 fn into_shape(self, shape: &Shape) -> crate::Result<Shape> {
553 let ((), d1) = self;
554 Ok((hole_size(shape, d1, &self)?, d1).into())
555 }
556}
557
558impl ShapeWithHolder for (usize, ()) {
559 fn into_shape(self, shape: &Shape) -> crate::Result<Shape> {
560 let (d1, ()) = self;
561 Ok((d1, hole_size(shape, d1, &self)?).into())
562 }
563}
564
565impl ShapeWithHolder for ((), usize, usize) {
566 fn into_shape(self, shape: &Shape) -> crate::Result<Shape> {
567 let ((), d1, d2) = self;
568 Ok((hole_size(shape, d1 * d2, &self)?, d1, d2).into())
569 }
570}
571
572impl ShapeWithHolder for (usize, (), usize) {
573 fn into_shape(self, shape: &Shape) -> crate::Result<Shape> {
574 let (d1, (), d2) = self;
575 Ok((d1, hole_size(shape, d1 * d2, &self)?, d2).into())
576 }
577}
578
579impl ShapeWithHolder for (usize, usize, ()) {
580 fn into_shape(self, shape: &Shape) -> crate::Result<Shape> {
581 let (d1, d2, ()) = self;
582 Ok((d1, d2, hole_size(shape, d1 * d2, &self)?).into())
583 }
584}
585
586impl ShapeWithHolder for ((), usize, usize, usize) {
587 fn into_shape(self, shape: &Shape) -> crate::Result<Shape> {
588 let ((), d1, d2, d3) = self;
589 let d = hole_size(shape, d1 * d2 * d3, &self)?;
590 Ok((d, d1, d2, d3).into())
591 }
592}
593
594impl ShapeWithHolder for (usize, (), usize, usize) {
595 fn into_shape(self, shape: &Shape) -> crate::Result<Shape> {
596 let (d1, (), d2, d3) = self;
597 let d = hole_size(shape, d1 * d2 * d3, &self)?;
598 Ok((d1, d, d2, d3).into())
599 }
600}
601
602impl ShapeWithHolder for (usize, usize, (), usize) {
603 fn into_shape(self, shape: &Shape) -> crate::Result<Shape> {
604 let (d1, d2, (), d3) = self;
605 let d = hole_size(shape, d1 * d2 * d3, &self)?;
606 Ok((d1, d2, d, d3).into())
607 }
608}
609
610impl ShapeWithHolder for (usize, usize, usize, ()) {
611 fn into_shape(self, shape: &Shape) -> crate::Result<Shape> {
612 let (d1, d2, d3, ()) = self;
613 let d = hole_size(shape, d1 * d2 * d3, &self)?;
614 Ok((d1, d2, d3, d).into())
615 }
616}
617
618impl ShapeWithHolder for ((), usize, usize, usize, usize) {
619 fn into_shape(self, shape: &Shape) -> crate::Result<Shape> {
620 let ((), d1, d2, d3, d4) = self;
621 let d = hole_size(shape, d1 * d2 * d3 * d4, &self)?;
622 Ok((d, d1, d2, d3, d4).into())
623 }
624}
625
626impl ShapeWithHolder for (usize, (), usize, usize, usize) {
627 fn into_shape(self, shape: &Shape) -> crate::Result<Shape> {
628 let (d1, (), d2, d3, d4) = self;
629 let d = hole_size(shape, d1 * d2 * d3 * d4, &self)?;
630 Ok((d1, d, d2, d3, d4).into())
631 }
632}
633
634impl ShapeWithHolder for (usize, usize, (), usize, usize) {
635 fn into_shape(self, shape: &Shape) -> crate::Result<Shape> {
636 let (d1, d2, (), d3, d4) = self;
637 let d = hole_size(shape, d1 * d2 * d3 * d4, &self)?;
638 Ok((d1, d2, d, d3, d4).into())
639 }
640}
641
642impl ShapeWithHolder for (usize, usize, usize, (), usize) {
643 fn into_shape(self, shape: &Shape) -> crate::Result<Shape> {
644 let (d1, d2, d3, (), d4) = self;
645 let d = hole_size(shape, d1 * d2 * d3 * d4, &self)?;
646 Ok((d1, d2, d3, d, d4).into())
647 }
648}
649
650impl ShapeWithHolder for (usize, usize, usize, usize, ()) {
651 fn into_shape(self, shape: &Shape) -> crate::Result<Shape> {
652 let (d1, d2, d3, d4, ()) = self;
653 let d = hole_size(shape, d1 * d2 * d3 * d4, &self)?;
654 Ok((d1, d2, d3, d4, d).into())
655 }
656}
657
658impl<T: WithDType> AsRef<Tensor<T>> for Tensor<T> {
659 fn as_ref(&self) -> &Tensor<T> {
660 self
661 }
662}
663
664#[cfg(test)]
665#[allow(unused)]
666mod test {
667 use super::*;
668
669 #[test]
670 fn test_unsqueeze_basic() -> Result<()> {
671 let t = Tensor::<i32>::zeros((2, 3))?;
672
673 let unsq0 = t.unsqueeze(0)?;
675 assert_eq!(unsq0.dims(), &[1, 2, 3]);
676 assert_eq!(unsq0.to_vec()?, t.to_vec()?);
677
678 let unsq1 = t.unsqueeze(1)?;
680 assert_eq!(unsq1.dims(), &[2, 1, 3]);
681 assert_eq!(unsq1.to_vec()?, t.to_vec()?);
682
683 let unsq2 = t.unsqueeze(2)?;
685 assert_eq!(unsq2.dims(), &[2, 3, 1]);
686 assert_eq!(unsq2.to_vec()?, t.to_vec()?);
687
688 Ok(())
689 }
690
691 #[test]
692 fn test_squeeze_basic() -> Result<()> {
693 let t = Tensor::<i32>::zeros((2, 1, 3))?;
694
695 let sq = t.squeeze(1)?;
696 assert_eq!(sq.dims(), &[2, 3]);
697 assert_eq!(sq.to_vec()?, t.to_vec()?);
698
699 let t2 = Tensor::<i32>::zeros((1, 5))?;
704 let sq2 = t2.squeeze(0)?;
705 assert_eq!(sq2.dims(), &[5]);
706
707 Ok(())
708 }
709
710 #[test]
711 fn test_squeeze_unsqueeze_consistency() -> Result<()> {
712 let t = Tensor::new(&[[1, 2, 3], [4, 5, 6]])?; let unsq = t.unsqueeze(0)?; let sq = unsq.squeeze(0)?; assert_eq!(t.dims(), sq.dims());
718 assert_eq!(t.to_vec()?, sq.to_vec()?);
719 Ok(())
720 }
721
722 #[test]
723 fn test_unsqueeze() -> Result<()> {
724 let t = Tensor::<i32>::zeros((2, 1, 3))?;
725 let sq = t.squeeze(1)?;
726 println!("{}", sq);
727 assert_eq!(sq.dims(), vec![2, 3]);
728
729 let unsq = sq.unsqueeze(0)?;
730 println!("{}", unsq);
731 assert_eq!(unsq.dims(), vec![1, 2, 3]);
732
733 Ok(())
734 }
735
736 #[test]
737 fn test_cat_3d() -> Result<()> {
738 let a = Tensor::full((2, 2, 2), 1)?;
739 let b = Tensor::full((2, 2, 2), 2)?;
740
741 let c = Tensor::cat(&[a, b], 0)?;
742 assert_eq!(c.dims(), [4, 2, 2]);
743
744 let c2 = Tensor::cat(&[c.clone(), c.clone()], 1)?;
745 assert_eq!(c2.dims(), [4, 4, 2]);
746
747 Ok(())
748 }
749
750 #[test]
751 fn test_cat_1d() -> Result<()> {
752 let a = Tensor::new(&[1, 2, 3])?;
753 let b = Tensor::new(&[4, 5, 6])?;
754 let c = Tensor::new(&[7])?;
755
756 let res = Tensor::cat(&[a, b, c], 0)?;
757 assert_eq!(res.dims(), &[7]);
758 assert_eq!(res.to_vec()?, &[1, 2, 3, 4, 5, 6, 7]);
759
760 Ok(())
761 }
762
763 #[test]
764 fn test_cat_2d_axis0() -> Result<()> {
765 let a = Tensor::new(&[[1, 2], [3, 4]])?; let b = Tensor::new(&[[5, 6]])?; let c = Tensor::cat(&[a, b], 0)?;
769 assert_eq!(c.dims(), &[3, 2]);
770 assert_eq!(c.to_vec()?, &[1, 2, 3, 4, 5, 6]);
771
772 Ok(())
773 }
774
775 #[test]
776 fn test_cat_2d_axis1() -> Result<()> {
777 let a = Tensor::new(&[[1, 2], [3, 4]])?; let b = Tensor::new(&[[5], [6]])?; let c = Tensor::cat(&[a, b], 1)?;
781 assert_eq!(c.dims(), &[2, 3]);
782 assert_eq!(c.to_vec()?, &[1, 2, 5, 3, 4, 6]);
784
785 Ok(())
786 }
787
788 #[test]
789 fn test_cat_shape_mismatch() {
790 let a = Tensor::new(&[[1, 2], [3, 4]]).unwrap(); let b = Tensor::new(&[[1, 2, 3]]).unwrap(); let res = Tensor::cat(&[a, b], 0);
796 assert!(res.is_err());
797 }
798
799 #[test]
800 fn test_cat_empty_list_error() {
801 let res = Tensor::<i32>::cat::<Tensor<i32>, usize>(&[], 0);
802 assert!(res.is_err(), "Concatenating an empty list should return an error");
803 }
804
805 #[test]
806 fn test_cat_bool() -> Result<()> {
807 let a = Tensor::new(&[[true, false]])?;
808 let b = Tensor::new(&[[false, true]])?;
809
810 let c = Tensor::cat(&[a, b], 0)?;
811 assert_eq!(c.dims(), [2, 2]);
812 assert_eq!(c.to_vec().unwrap(), [true, false, false, true]);
813
814 Ok(())
815 }
816
817 #[test]
818 fn test_stack_1d_axis0() -> Result<()> {
819 let a = Tensor::new(&[1, 2, 3])?;
820 let b = Tensor::new(&[4, 5, 6])?;
821
822 let c = Tensor::stack(&[a, b], 0)?;
823 assert_eq!(c.dims(), [2, 3]);
824 assert_eq!(c.to_vec().unwrap(), [1, 2, 3, 4, 5, 6]);
825
826 Ok(())
827 }
828
829 #[test]
830 fn test_stack_1d_axis1() -> Result<()> {
831 let a = Tensor::new(&[1, 2, 3])?;
832 let b = Tensor::new(&[4, 5, 6])?;
833
834 let c = Tensor::stack(&[a, b], 1)?;
835 assert_eq!(c.dims(), [3, 2]);
836 assert_eq!(c.to_vec().unwrap(), [1, 4, 2, 5, 3, 6]);
837
838 Ok(())
839 }
840
841 #[test]
842 fn test_stack_2d_axis0() -> Result<()> {
843 let a = Tensor::new(&[[1, 2], [3, 4]])?;
844 let b = Tensor::new(&[[5, 6], [7, 8]])?;
845
846 let c = Tensor::stack(&[a, b], 0)?;
847 assert_eq!(c.dims(), [2, 2, 2]);
848 assert_eq!(c.to_vec().unwrap(), [1, 2, 3, 4, 5, 6, 7, 8]);
849
850 Ok(())
851 }
852
853 #[test]
854 fn test_stack_2d_axis1() -> Result<()> {
855 let a = Tensor::new(&[[1, 2], [3, 4]])?;
856 let b = Tensor::new(&[[5, 6], [7, 8]])?;
857
858 let c = Tensor::stack(&[a, b], 1)?;
859 assert_eq!(c.dims(), [2, 2, 2]);
860 assert_eq!(c.to_vec().unwrap(), [1, 2, 5, 6, 3, 4, 7, 8]);
861
862 Ok(())
863 }
864
865 #[test]
866 fn test_stack_2d_axis2() -> Result<()> {
867 let a = Tensor::new(&[[1, 2], [3, 4]])?;
868 let b = Tensor::new(&[[5, 6], [7, 8]])?;
869
870 let c = Tensor::stack(&[a, b], 2)?;
871 assert_eq!(c.dims(), [2, 2, 2]);
872 assert_eq!(c.to_vec().unwrap(), [1, 5, 2, 6, 3, 7, 4, 8]);
873
874 Ok(())
875 }
876
877 #[test]
878 fn test_stack_shape_mismatch() {
879 let a = Tensor::new(&[1, 2, 3]).unwrap();
880 let b = Tensor::new(&[4, 5]).unwrap();
881
882 let res = Tensor::stack(&[a, b], 0);
883 assert!(res.is_err());
884 }
885
886 #[test]
887 fn test_split_1d() -> Result<()> {
888 let a = Tensor::new(&[10, 20, 30, 40])?;
889 let splits = a.split(0)?; assert_eq!(splits.len(), 4);
892 assert_eq!(splits[0].to_vec().unwrap(), [10]);
893 assert_eq!(splits[1].to_vec().unwrap(), [20]);
894 assert_eq!(splits[2].to_vec().unwrap(), [30]);
895 assert_eq!(splits[3].to_vec().unwrap(), [40]);
896
897 Ok(())
898 }
899
900 #[test]
901 fn test_split_2d_axis0() -> Result<()> {
902 let a = Tensor::new(&[[1, 2], [3, 4], [5, 6], [7, 8]])?;
903 let splits = a.split(0)?;
904
905 assert_eq!(splits.len(), 4);
906 assert_eq!(splits[0].to_vec().unwrap(), [1, 2]);
907 assert_eq!(splits[1].to_vec().unwrap(), [3, 4]);
908 assert_eq!(splits[2].to_vec().unwrap(), [5, 6]);
909 assert_eq!(splits[3].to_vec().unwrap(), [7, 8]);
910
911 Ok(())
912 }
913
914 #[test]
915 fn test_split_2d_axis1() -> Result<()> {
916 let a = Tensor::new(&[[1, 2, 3], [4, 5, 6]])?;
917 let splits = a.split(1)?;
918
919 assert_eq!(splits.len(), 3);
920 assert_eq!(splits[0].to_vec().unwrap(), [1, 4]);
921 assert_eq!(splits[1].to_vec().unwrap(), [2, 5]);
922 assert_eq!(splits[2].to_vec().unwrap(), [3, 6]);
923
924 Ok(())
925 }
926
927 #[test]
928 fn test_split_3d_axis2() -> Result<()> {
929 let a = Tensor::new(&[
930 [[1, 2], [3, 4]],
931 [[5, 6], [7, 8]]
932 ])?;
933 let splits = a.split(2)?;
934
935 assert_eq!(splits.len(), 2);
936 assert_eq!(splits[0].to_vec().unwrap(), [1, 3, 5, 7]);
937 assert_eq!(splits[1].to_vec().unwrap(), [2, 4, 6, 8]);
938
939 Ok(())
940 }
941
942 #[test]
943 fn test_split_single_element() -> Result<()> {
944 let a = Tensor::new(&[42])?;
945 let splits = a.split(0)?;
946
947 assert_eq!(splits.len(), 1);
948 assert_eq!(splits[0].to_vec().unwrap(), [42]);
949
950 Ok(())
951 }
952
953 #[test]
954 fn test_split_empty_array() -> Result<()> {
955 let a = Tensor::<i32>::zeros((0, 2))?;
956 let splits = a.split(0)?;
957
958 assert!(splits.is_empty());
959 Ok(())
960 }
961
962 #[test]
963 fn test_repeat_1d() -> Result<()> {
964 let a = Tensor::new(&[1, 2, 3])?;
965 let b = a.repeat(3)?; assert_eq!(b.dims(), [3 * 3]); assert_eq!(b.to_vec().unwrap(), [1, 2, 3, 1, 2, 3, 1, 2, 3]);
968 Ok(())
969 }
970
971 #[test]
972 fn test_reshape_with_holder() -> Result<()> {
973 let a = Tensor::<f32>::zeros((3, 3, 3))?;
974 let b = a.reshape(((), 3))?;
975 assert_eq!(b.dims2()?, (9, 3));
976
977 let a = Tensor::<f32>::zeros((9, 12, 3))?;
978 let b = a.reshape((1, 1, ()))?;
979 assert_eq!(b.dims3()?, (1, 1, 9 * 12 * 3));
980 Ok(())
981 }
982
983 #[test]
984 fn test_repeat_2d() -> Result<()> {
985 let a = Tensor::new(&[[1, 2], [3, 4]])?;
986 let b = a.repeat((2, 3))?; assert_eq!(b.dims(), [4, 6]);
988 assert_eq!(
989 b.to_vec().unwrap(),
990 [
991 1, 2, 1, 2, 1, 2,
992 3, 4, 3, 4, 3, 4,
993 1, 2, 1, 2, 1, 2,
994 3, 4, 3, 4, 3, 4
995 ]
996 );
997 Ok(())
998 }
999
1000 #[test]
1001 fn test_repeat_dim() -> Result<()> {
1002 let a = Tensor::new(&[1, 2, 3])?;
1003 let b = a.repeat_dim(0, 2)?; assert_eq!(b.dims(), [6]);
1005 assert_eq!(b.to_vec().unwrap(), [1, 2, 3, 1, 2, 3]);
1006
1007 let c = a.repeat_dim(0, 1)?; assert_eq!(c.dims(), [3]);
1009 assert_eq!(c.to_vec().unwrap(), [1, 2, 3]);
1010
1011 Ok(())
1012 }
1013
1014 #[test]
1015 fn test_repeat_high_dim() -> Result<()> {
1016 let a = Tensor::new(&[[1, 2], [3, 4]])?;
1017 let b = a.repeat((2, 3))?; assert_eq!(b.dims(), [4, 6]);
1019 Ok(())
1020 }
1021
1022 #[test]
1023 fn test_narrow_1d_basic() -> Result<()> {
1024 let a = Tensor::new(&[0, 1, 2, 3, 4, 5])?;
1025
1026 let b = a.narrow(0, 2, 3)?;
1027
1028 assert_eq!(b.dims(), &[3]);
1029 assert_eq!(b.to_vec().unwrap(), &[2, 3, 4]);
1030
1031 let b = Tensor::randn(0.0, 1.0, (5, 5))?;
1032 println!("{:?}", b);
1033 Ok(())
1034 }
1035
1036 #[test]
1037 fn test_narrow_2d_rows() -> Result<()> {
1038 let a = Tensor::new(&[
1043 [0, 1, 2],
1044 [3, 4, 5],
1045 [6, 7, 8]
1046 ])?;
1047
1048 let b = a.narrow(0, 1, 1)?;
1049
1050 assert_eq!(b.dims(), &[1, 3]);
1051 assert_eq!(b.to_vec().unwrap(), &[3, 4, 5]);
1052 Ok(())
1053 }
1054}