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