1use crate::dimension::Dimension;
4use crate::dtype::{DType, Element};
5use crate::error::{FerrayError, FerrayResult};
6
7use super::ArrayFlags;
8use super::owned::Array;
9use super::view::ArrayView;
10
11impl<T: Element, D: Dimension> Array<T, D> {
16 #[inline]
18 pub fn itemsize(&self) -> usize {
19 std::mem::size_of::<T>()
20 }
21
22 #[inline]
24 pub fn nbytes(&self) -> usize {
25 self.size() * self.itemsize()
26 }
27
28 #[inline]
30 pub fn dtype(&self) -> DType {
31 T::dtype()
32 }
33
34 pub fn t(&self) -> ArrayView<'_, T, D> {
40 let transposed = self.inner.view().reversed_axes();
41 ArrayView::from_ndarray(transposed)
42 }
43
44 pub fn copy(&self) -> Self {
46 Self {
47 inner: self.inner.clone(),
48 dim: self.dim.clone(),
49 }
50 }
51
52 pub fn to_vec_flat(&self) -> Vec<T> {
54 self.inner.iter().cloned().collect()
55 }
56
57 pub fn to_bytes(&self) -> FerrayResult<&[u8]>
62 where
63 T: Copy,
64 {
65 let slice = self.inner.as_slice().ok_or_else(|| {
66 FerrayError::invalid_value("array is not contiguous; cannot produce byte slice")
67 })?;
68 let ptr = slice.as_ptr() as *const u8;
69 let len = std::mem::size_of_val(slice);
70 Ok(unsafe { std::slice::from_raw_parts(ptr, len) })
73 }
74
75 pub fn flags(&self) -> ArrayFlags {
77 let layout = self.layout();
78 ArrayFlags {
79 c_contiguous: layout.is_c_contiguous(),
80 f_contiguous: layout.is_f_contiguous(),
81 owndata: true,
82 writeable: true,
83 }
84 }
85}
86
87impl<T: Element, D: Dimension> ArrayView<'_, T, D> {
92 #[inline]
94 pub fn itemsize(&self) -> usize {
95 std::mem::size_of::<T>()
96 }
97
98 #[inline]
100 pub fn nbytes(&self) -> usize {
101 self.size() * self.itemsize()
102 }
103
104 #[inline]
106 pub fn dtype(&self) -> DType {
107 T::dtype()
108 }
109
110 pub fn t(&self) -> ArrayView<'_, T, D> {
112 let transposed = self.inner.clone().reversed_axes();
113 ArrayView::from_ndarray(transposed)
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120 use crate::dimension::{Ix1, Ix2};
121
122 #[test]
123 fn introspect_basics() {
124 let arr = Array::<f64, Ix2>::from_vec(Ix2::new([2, 3]), vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
125 .unwrap();
126
127 assert_eq!(arr.ndim(), 2);
128 assert_eq!(arr.size(), 6);
129 assert_eq!(arr.shape(), &[2, 3]);
130 assert_eq!(arr.itemsize(), 8); assert_eq!(arr.nbytes(), 48); assert_eq!(arr.dtype(), DType::F64);
133 assert!(!arr.is_empty());
134 }
135
136 #[test]
137 fn introspect_empty() {
138 let arr = Array::<f64, Ix1>::from_vec(Ix1::new([0]), vec![]).unwrap();
139 assert!(arr.is_empty());
140 assert_eq!(arr.size(), 0);
141 assert_eq!(arr.nbytes(), 0);
142 }
143
144 #[test]
145 fn flags_owned() {
146 let arr = Array::<f64, Ix2>::zeros(Ix2::new([3, 4])).unwrap();
147 let f = arr.flags();
148 assert!(f.c_contiguous);
149 assert!(f.owndata);
150 assert!(f.writeable);
151 }
152
153 #[test]
154 fn transpose_view() {
155 let arr = Array::<f64, Ix2>::from_vec(Ix2::new([2, 3]), vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
156 .unwrap();
157 let t = arr.t();
158 assert_eq!(t.shape(), &[3, 2]);
159 assert_eq!(t.size(), 6);
160 }
161
162 #[test]
163 fn copy_is_independent() {
164 let arr = Array::<f64, Ix1>::from_vec(Ix1::new([3]), vec![1.0, 2.0, 3.0]).unwrap();
165 let copy = arr.copy();
166 assert_eq!(copy.as_slice().unwrap(), arr.as_slice().unwrap());
167 assert_ne!(copy.as_ptr(), arr.as_ptr());
168 }
169
170 #[test]
171 fn to_vec_flat() {
172 let arr = Array::<i32, Ix2>::from_vec(Ix2::new([2, 2]), vec![1, 2, 3, 4]).unwrap();
173 assert_eq!(arr.to_vec_flat(), vec![1, 2, 3, 4]);
174 }
175
176 #[test]
177 fn to_bytes_contiguous() {
178 let arr = Array::<u8, Ix1>::from_vec(Ix1::new([4]), vec![0xDE, 0xAD, 0xBE, 0xEF]).unwrap();
179 let bytes = arr.to_bytes().unwrap();
180 assert_eq!(bytes, &[0xDE, 0xAD, 0xBE, 0xEF]);
181 }
182
183 #[test]
184 fn view_introspection() {
185 let arr = Array::<f64, Ix2>::from_vec(Ix2::new([2, 3]), vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
186 .unwrap();
187 let v = arr.view();
188 assert_eq!(v.itemsize(), 8);
189 assert_eq!(v.nbytes(), 48);
190 assert_eq!(v.dtype(), DType::F64);
191 }
192
193 #[test]
194 fn view_transpose() {
195 let arr = Array::<f64, Ix2>::from_vec(Ix2::new([2, 3]), vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
196 .unwrap();
197 let v = arr.view();
198 let vt = v.t();
199 assert_eq!(vt.shape(), &[3, 2]);
200 }
201}