1use std::{
2 fmt::{Debug, Display},
3 marker::PhantomData,
4 ops::Mul,
5};
6
7use derive_more::derive::Display;
8use serde::{Deserialize, Serialize};
9use typenum::Prod;
10
11use super::HeapArray;
12use crate::{
13 errors::PrimitiveError,
14 random::{CryptoRngCore, Random},
15 types::Positive,
16};
17
18#[derive(Display, Default, Clone, Copy, PartialEq, Eq)]
20pub struct ColumnMajor;
21#[derive(Display, Default, Clone, Copy, PartialEq, Eq)]
23pub struct RowMajor;
24
25pub type RowMajorHeapMatrix<T, M, N> = HeapMatrix<T, M, N, RowMajor>;
26
27#[derive(Clone, PartialEq, Eq)]
31#[repr(C)]
32pub struct HeapMatrix<T: Sized, M: Positive, N: Positive, O = ColumnMajor> {
33 pub(super) data: Box<[T]>,
34
35 #[allow(clippy::type_complexity)]
39 pub(super) _len: PhantomData<fn() -> (M, N, O)>,
40}
41impl<T: Sized, M: Positive, N: Positive, O> HeapMatrix<T, M, N, O> {
42 fn new(data: Box<[T]>) -> Self {
43 Self {
44 data,
45 _len: PhantomData,
46 }
47 }
48
49 pub fn flat_iter(&self) -> impl ExactSizeIterator<Item = &T> {
51 self.data.iter()
52 }
53
54 pub fn flat_iter_mut(&mut self) -> impl ExactSizeIterator<Item = &mut T> {
56 self.data.iter_mut()
57 }
58
59 pub fn into_flat_iter(self) -> impl ExactSizeIterator<Item = T> {
61 self.data.into_vec().into_iter()
62 }
63
64 pub const fn len(&self) -> usize {
66 M::USIZE * N::USIZE
67 }
68
69 pub const fn is_empty(&self) -> bool {
71 self.len() == 0
72 }
73
74 pub const fn rows(&self) -> usize {
76 M::USIZE
77 }
78
79 pub const fn cols(&self) -> usize {
81 N::USIZE
82 }
83}
84
85impl<T: Sized, M: Positive, N: Positive, O> HeapMatrix<T, M, N, O> {
86 pub fn map<F, U>(self, f: F) -> HeapMatrix<U, M, N, O>
87 where
88 F: FnMut(T) -> U,
89 {
90 HeapMatrix::new(
91 self.data
92 .into_vec()
93 .into_iter()
94 .map(f)
95 .collect::<Box<[U]>>(),
96 )
97 }
98}
99
100impl<T: Sized, M: Positive + Mul<N, Output: Positive>, N: Positive, O> HeapMatrix<T, M, N, O> {
101 pub fn into_flat_array(self) -> HeapArray<T, Prod<M, N>> {
103 HeapArray::new(self.data)
104 }
105
106 pub fn from_flat_array(value: HeapArray<T, Prod<M, N>>) -> Self {
108 Self::new(value.data)
109 }
110}
111
112impl<T: Sized, M: Positive, N: Positive> HeapMatrix<T, M, N, ColumnMajor> {
115 pub fn col_iter(&self) -> impl ExactSizeIterator<Item = &[T]> {
117 self.data.chunks_exact(M::USIZE)
118 }
119
120 pub fn col_iter_mut(&mut self) -> impl ExactSizeIterator<Item = &mut [T]> {
122 self.data.chunks_exact_mut(M::USIZE)
123 }
124
125 pub fn get(&self, row: usize, col: usize) -> Option<&T> {
127 (row < M::USIZE && col < N::USIZE)
128 .then(|| unsafe { self.data.get_unchecked(col * M::USIZE + row) })
129 }
130
131 pub fn get_mut(&mut self, row: usize, col: usize) -> Option<&mut T> {
133 (row < M::USIZE && col < N::USIZE)
134 .then(|| unsafe { self.data.get_unchecked_mut(col * M::USIZE + row) })
135 }
136}
137
138impl<T: Sized, M: Positive + Mul<N, Output: Positive>, N: Positive>
139 HeapMatrix<T, M, N, ColumnMajor>
140{
141 pub fn from_cols(val: HeapArray<HeapArray<T, M>, N>) -> Self {
143 Self::try_from(val.into_iter().flatten().collect::<Box<[T]>>()).unwrap()
144 }
145}
146
147impl<T: Sized, M: Positive, N: Positive> HeapMatrix<T, M, N, RowMajor> {
150 pub fn row_iter(&self) -> impl ExactSizeIterator<Item = &[T]> {
152 self.data.chunks_exact(N::USIZE)
153 }
154
155 pub fn row_iter_mut(&mut self) -> impl ExactSizeIterator<Item = &mut [T]> {
157 self.data.chunks_exact_mut(N::USIZE)
158 }
159
160 pub fn get(&self, row: usize, col: usize) -> Option<&T> {
162 (row < M::USIZE && col < N::USIZE)
163 .then(|| unsafe { self.data.get_unchecked(row * N::USIZE + col) })
164 }
165
166 pub fn get_mut(&mut self, row: usize, col: usize) -> Option<&mut T> {
168 (row < M::USIZE && col < N::USIZE)
169 .then(|| unsafe { self.data.get_unchecked_mut(row * N::USIZE + col) })
170 }
171}
172
173impl<T: Sized, M: Positive + Mul<N, Output: Positive>, N: Positive>
174 HeapMatrix<T, M, N, ColumnMajor>
175{
176 pub fn from_rows(val: HeapArray<HeapArray<T, N>, M>) -> Self {
178 Self::try_from(val.into_iter().flatten().collect::<Box<[T]>>()).unwrap()
179 }
180}
181
182impl<T: Sized + Default, M: Positive, N: Positive, O> Default for HeapMatrix<T, M, N, O> {
185 fn default() -> Self {
186 Self::new(
187 (0..M::USIZE * N::USIZE)
188 .map(|_| T::default())
189 .collect::<Box<[T]>>(),
190 )
191 }
192}
193
194impl<T: Sized + Debug, M: Positive, N: Positive, O: Display + Default> Debug
195 for HeapMatrix<T, M, N, O>
196{
197 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
198 f.debug_struct(format!("Matrix[{}]<{}, {}>", O::default(), M::USIZE, N::USIZE).as_str())
199 .field("data", &self.data)
200 .finish()
201 }
202}
203
204impl<T: Sized + Serialize, M: Positive, N: Positive, O> Serialize for HeapMatrix<T, M, N, O> {
205 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
206 self.data.serialize(serializer)
207 }
208}
209
210impl<T: Random + Sized, M: Positive, N: Positive, O: 'static> Random for HeapMatrix<T, M, N, O> {
211 fn random(mut rng: impl CryptoRngCore) -> Self {
212 Self::new(T::random_n(&mut rng, M::USIZE * N::USIZE))
213 }
214}
215
216impl<'de, T: Sized + Deserialize<'de>, M: Positive, N: Positive, O> Deserialize<'de>
217 for HeapMatrix<T, M, N, O>
218{
219 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
220 let data = Box::<[T]>::deserialize(deserializer)?;
221 if data.len() != M::USIZE * N::USIZE {
222 return Err(serde::de::Error::custom(format!(
223 "Expected matrix of length {}, got {}",
224 M::USIZE * N::USIZE,
225 data.len()
226 )));
227 }
228 Ok(Self::new(data))
229 }
230}
231
232impl<T: Sized, M: Positive, N: Positive, O> AsRef<[T]> for HeapMatrix<T, M, N, O> {
233 fn as_ref(&self) -> &[T] {
234 &self.data
235 }
236}
237
238impl<T: Sized, M: Positive, N: Positive, O> AsMut<[T]> for HeapMatrix<T, M, N, O> {
239 fn as_mut(&mut self) -> &mut [T] {
240 &mut self.data
241 }
242}
243
244impl<T: Sized, M: Positive, N: Positive, O> From<HeapMatrix<T, M, N, O>> for Vec<T> {
245 fn from(matrix: HeapMatrix<T, M, N, O>) -> Self {
246 matrix.data.into_vec()
247 }
248}
249
250impl<T: Sized, M: Positive, N: Positive, O> TryFrom<Vec<T>> for HeapMatrix<T, M, N, O> {
251 type Error = PrimitiveError;
252
253 fn try_from(matrix: Vec<T>) -> Result<Self, Self::Error> {
254 if matrix.len() != M::USIZE * N::USIZE {
255 return Err(PrimitiveError::InvalidSize(
256 M::USIZE * N::USIZE,
257 matrix.len(),
258 ));
259 }
260 Ok(Self::new(matrix.into_boxed_slice()))
261 }
262}
263
264impl<T: Sized, M: Positive, N: Positive, O> From<HeapMatrix<T, M, N, O>> for Box<[T]> {
265 fn from(matrix: HeapMatrix<T, M, N, O>) -> Self {
266 matrix.data
267 }
268}
269
270impl<T: Sized, M: Positive, N: Positive, O> TryFrom<Box<[T]>> for HeapMatrix<T, M, N, O> {
271 type Error = PrimitiveError;
272
273 fn try_from(matrix: Box<[T]>) -> Result<Self, Self::Error> {
274 if matrix.len() != M::USIZE * N::USIZE {
275 return Err(PrimitiveError::InvalidSize(
276 M::USIZE * N::USIZE,
277 matrix.len(),
278 ));
279 }
280 Ok(Self::new(matrix))
281 }
282}
283
284#[cfg(test)]
285pub mod tests {
286 use itertools::Itertools;
287 use typenum::{U2, U3, U4, U6};
288
289 use super::{ColumnMajor, RowMajor};
290 use crate::types::{HeapArray, HeapMatrix};
291
292 #[test]
293 fn test_flat_operations() {
294 let data: Vec<u32> = (0..6).collect();
295 let matrix: HeapMatrix<u32, U2, U3> = HeapMatrix::new(data.clone().into_boxed_slice());
296
297 assert_eq!(matrix.flat_iter().copied().collect_vec(), data);
299
300 let mut matrix3: HeapMatrix<u32, U2, U3> = HeapMatrix::new(data.clone().into_boxed_slice());
302 for x in matrix3.flat_iter_mut() {
303 *x *= 2;
304 }
305 assert_eq!(matrix3.get(0, 0), Some(&0));
306 assert_eq!(matrix3.get(1, 0), Some(&2));
307
308 let array: HeapArray<u32, U6> = matrix.into_flat_array();
310 assert_eq!(array.as_ref(), data.as_slice());
311 let matrix4: HeapMatrix<u32, U2, U3> = HeapMatrix::from_flat_array(array);
312 assert_eq!(matrix4.as_ref(), data.as_slice());
313 }
314
315 #[test]
316 fn test_column_first_operations() {
317 let data: Vec<u32> = vec![0, 1, 2, 3, 4, 5];
319 let mut matrix: HeapMatrix<u32, U3, U2, ColumnMajor> =
320 HeapMatrix::new(data.into_boxed_slice());
321
322 assert_eq!(matrix.get(0, 0), Some(&0));
324 assert_eq!(matrix.get(1, 0), Some(&1));
325 assert_eq!(matrix.get(2, 0), Some(&2));
326 assert_eq!(matrix.get(0, 1), Some(&3));
327 assert_eq!(matrix.get(1, 1), Some(&4));
328 assert_eq!(matrix.get(2, 1), Some(&5));
329 assert_eq!(matrix.get(3, 0), None);
330 assert_eq!(matrix.get(0, 2), None);
331
332 *matrix.get_mut(1, 1).unwrap() = 42;
334 assert_eq!(matrix.get(1, 1), Some(&42));
335
336 let data2: Vec<u32> = (0..12).collect();
338 let matrix2: HeapMatrix<u32, U4, U3, ColumnMajor> =
339 HeapMatrix::new(data2.into_boxed_slice());
340 let cols: Vec<Vec<u32>> = matrix2.col_iter().map(|col| col.to_vec()).collect();
341 assert_eq!(cols.len(), 3);
342 assert_eq!(cols[0], vec![0, 1, 2, 3]);
343 assert_eq!(cols[1], vec![4, 5, 6, 7]);
344 assert_eq!(cols[2], vec![8, 9, 10, 11]);
345
346 let data3: Vec<u32> = (0..12).collect();
348 let mut matrix3: HeapMatrix<u32, U4, U3, ColumnMajor> =
349 HeapMatrix::new(data3.into_boxed_slice());
350 for col in matrix3.col_iter_mut() {
351 col[0] = 99;
352 }
353 assert_eq!(matrix3.get(0, 0), Some(&99));
354 assert_eq!(matrix3.get(0, 1), Some(&99));
355 assert_eq!(matrix3.get(0, 2), Some(&99));
356 }
357
358 #[test]
359 fn test_row_first_operations() {
360 let data: Vec<u32> = vec![0, 1, 2, 3, 4, 5];
362 let mut matrix: HeapMatrix<u32, U3, U2, RowMajor> =
363 HeapMatrix::new(data.into_boxed_slice());
364
365 assert_eq!(matrix.get(0, 0), Some(&0));
367 assert_eq!(matrix.get(0, 1), Some(&1));
368 assert_eq!(matrix.get(1, 0), Some(&2));
369 assert_eq!(matrix.get(1, 1), Some(&3));
370 assert_eq!(matrix.get(2, 0), Some(&4));
371 assert_eq!(matrix.get(2, 1), Some(&5));
372 assert_eq!(matrix.get(3, 0), None);
373 assert_eq!(matrix.get(0, 2), None);
374
375 *matrix.get_mut(1, 1).unwrap() = 42;
377 assert_eq!(matrix.get(1, 1), Some(&42));
378
379 let data2: Vec<u32> = (0..12).collect();
381 let matrix2: HeapMatrix<u32, U3, U4, RowMajor> = HeapMatrix::new(data2.into_boxed_slice());
382 let rows: Vec<Vec<u32>> = matrix2.row_iter().map(|row| row.to_vec()).collect();
383 assert_eq!(rows.len(), 3);
384 assert_eq!(rows[0], vec![0, 1, 2, 3]);
385 assert_eq!(rows[1], vec![4, 5, 6, 7]);
386 assert_eq!(rows[2], vec![8, 9, 10, 11]);
387
388 let data3: Vec<u32> = (0..12).collect();
390 let mut matrix3: HeapMatrix<u32, U3, U4, RowMajor> =
391 HeapMatrix::new(data3.into_boxed_slice());
392 for row in matrix3.row_iter_mut() {
393 row[0] = 99;
394 }
395 assert_eq!(matrix3.get(0, 0), Some(&99));
396 assert_eq!(matrix3.get(1, 0), Some(&99));
397 assert_eq!(matrix3.get(2, 0), Some(&99));
398 }
399
400 #[test]
401 fn test_try_from_vec() {
402 let data: Vec<u32> = (0..12).collect();
404 let result: Result<HeapMatrix<u32, U3, U4>, _> = data.try_into();
405 assert!(result.is_ok());
406
407 let data: Vec<u32> = (0..10).collect();
409 let result: Result<HeapMatrix<u32, U3, U4>, _> = data.try_into();
410 assert!(result.is_err());
411 }
412}