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]> {
61 let slice = self.inner.as_slice().ok_or_else(|| {
62 FerrayError::invalid_value("array is not contiguous; cannot produce byte slice")
63 })?;
64 let ptr = slice.as_ptr() as *const u8;
65 let len = std::mem::size_of_val(slice);
66 Ok(unsafe { std::slice::from_raw_parts(ptr, len) })
69 }
70
71 pub fn flags(&self) -> ArrayFlags {
73 let layout = self.layout();
74 ArrayFlags {
75 c_contiguous: layout.is_c_contiguous(),
76 f_contiguous: layout.is_f_contiguous(),
77 owndata: true,
78 writeable: true,
79 }
80 }
81}
82
83impl<T: Element, D: Dimension> ArrayView<'_, T, D> {
88 #[inline]
90 pub fn itemsize(&self) -> usize {
91 std::mem::size_of::<T>()
92 }
93
94 #[inline]
96 pub fn nbytes(&self) -> usize {
97 self.size() * self.itemsize()
98 }
99
100 #[inline]
102 pub fn dtype(&self) -> DType {
103 T::dtype()
104 }
105
106 pub fn t(&self) -> ArrayView<'_, T, D> {
108 let transposed = self.inner.clone().reversed_axes();
109 ArrayView::from_ndarray(transposed)
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116 use crate::dimension::{Ix1, Ix2};
117
118 #[test]
119 fn introspect_basics() {
120 let arr = Array::<f64, Ix2>::from_vec(Ix2::new([2, 3]), vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
121 .unwrap();
122
123 assert_eq!(arr.ndim(), 2);
124 assert_eq!(arr.size(), 6);
125 assert_eq!(arr.shape(), &[2, 3]);
126 assert_eq!(arr.itemsize(), 8); assert_eq!(arr.nbytes(), 48); assert_eq!(arr.dtype(), DType::F64);
129 assert!(!arr.is_empty());
130 }
131
132 #[test]
133 fn introspect_empty() {
134 let arr = Array::<f64, Ix1>::from_vec(Ix1::new([0]), vec![]).unwrap();
135 assert!(arr.is_empty());
136 assert_eq!(arr.size(), 0);
137 assert_eq!(arr.nbytes(), 0);
138 }
139
140 #[test]
141 fn flags_owned() {
142 let arr = Array::<f64, Ix2>::zeros(Ix2::new([3, 4])).unwrap();
143 let f = arr.flags();
144 assert!(f.c_contiguous);
145 assert!(f.owndata);
146 assert!(f.writeable);
147 }
148
149 #[test]
150 fn transpose_view() {
151 let arr = Array::<f64, Ix2>::from_vec(Ix2::new([2, 3]), vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
152 .unwrap();
153 let t = arr.t();
154 assert_eq!(t.shape(), &[3, 2]);
155 assert_eq!(t.size(), 6);
156 }
157
158 #[test]
159 fn copy_is_independent() {
160 let arr = Array::<f64, Ix1>::from_vec(Ix1::new([3]), vec![1.0, 2.0, 3.0]).unwrap();
161 let copy = arr.copy();
162 assert_eq!(copy.as_slice().unwrap(), arr.as_slice().unwrap());
163 assert_ne!(copy.as_ptr(), arr.as_ptr());
164 }
165
166 #[test]
167 fn to_vec_flat() {
168 let arr = Array::<i32, Ix2>::from_vec(Ix2::new([2, 2]), vec![1, 2, 3, 4]).unwrap();
169 assert_eq!(arr.to_vec_flat(), vec![1, 2, 3, 4]);
170 }
171
172 #[test]
173 fn to_bytes_contiguous() {
174 let arr = Array::<u8, Ix1>::from_vec(Ix1::new([4]), vec![0xDE, 0xAD, 0xBE, 0xEF]).unwrap();
175 let bytes = arr.to_bytes().unwrap();
176 assert_eq!(bytes, &[0xDE, 0xAD, 0xBE, 0xEF]);
177 }
178
179 #[test]
180 fn view_introspection() {
181 let arr = Array::<f64, Ix2>::from_vec(Ix2::new([2, 3]), vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
182 .unwrap();
183 let v = arr.view();
184 assert_eq!(v.itemsize(), 8);
185 assert_eq!(v.nbytes(), 48);
186 assert_eq!(v.dtype(), DType::F64);
187 }
188
189 #[test]
190 fn view_transpose() {
191 let arr = Array::<f64, Ix2>::from_vec(Ix2::new([2, 3]), vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
192 .unwrap();
193 let v = arr.view();
194 let vt = v.t();
195 assert_eq!(vt.shape(), &[3, 2]);
196 }
197}