rten_tensor/
contiguous.rs1use std::ops::Deref;
2
3use crate::layout::FromShape;
4use crate::storage::{CowData, ViewData};
5use crate::{AsView, Layout, Storage, TensorBase};
6
7#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
12pub struct Contiguous<T>(T);
13
14impl<T> Deref for Contiguous<T> {
15 type Target = T;
16
17 fn deref(&self) -> &T {
18 &self.0
19 }
20}
21
22impl<T> Contiguous<T> {
23 pub fn into_inner(self) -> T {
25 self.0
26 }
27}
28
29impl<S: Storage, L: Layout> Contiguous<TensorBase<S, L>> {
30 pub fn new(inner: TensorBase<S, L>) -> Option<Self> {
33 if inner.is_contiguous() {
34 Some(Self(inner))
35 } else {
36 None
37 }
38 }
39
40 pub fn data(&self) -> &[S::Elem] {
45 let len = self.0.len();
46 let ptr = self.0.data_ptr();
47
48 unsafe { std::slice::from_raw_parts(ptr, len) }
50 }
51
52 pub fn view(&self) -> Contiguous<TensorBase<ViewData<'_, S::Elem>, L>>
54 where
55 TensorBase<S, L>: AsView<Elem = S::Elem, Layout = L>,
56 {
57 Contiguous(self.0.view())
58 }
59}
60
61impl<T, L: Clone + Layout> Contiguous<TensorBase<Vec<T>, L>> {
62 pub fn from_owned(mut inner: TensorBase<Vec<T>, L>) -> Self
67 where
68 L: FromShape,
69 T: Clone,
70 {
71 inner.make_contiguous();
72 Self(inner)
73 }
74
75 pub fn into_data(self) -> Vec<T> {
77 self.0.into_non_contiguous_data()
78 }
79}
80
81impl<'a, T, L: Clone + Layout> Contiguous<TensorBase<CowData<'a, T>, L>> {
82 pub fn into_data(self) -> Option<Vec<T>> {
84 self.0.into_non_contiguous_data()
85 }
86}
87
88impl<S: Storage, L: Layout> From<Contiguous<TensorBase<S, L>>> for TensorBase<S, L> {
89 fn from(val: Contiguous<TensorBase<S, L>>) -> Self {
90 val.0
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use crate::{AsView, Contiguous, Layout, NdTensor};
97
98 #[test]
99 fn test_contiguous() {
100 let tensor = NdTensor::<f32, 2>::zeros([3, 3]);
101 let wrapped = Contiguous::new(tensor);
102 assert!(wrapped.is_some());
103
104 let mut tensor: NdTensor<f32, 2> = wrapped.unwrap().into();
105 tensor.transpose();
106 let wrapped = Contiguous::new(tensor);
107 assert!(wrapped.is_none());
108 }
109
110 #[test]
111 fn test_contiguous_view() {
112 let tensor = NdTensor::<f32, 2>::zeros([3, 4]);
113 let wrapped = Contiguous::new(tensor).unwrap();
114 assert_eq!(wrapped.view().shape(), [3, 4]);
115 }
116}