1use std::{alloc::Layout, iter::FusedIterator, marker::PhantomData, ptr::NonNull};
31
32use diskann_utils::{Reborrow, ReborrowMut, views::MatrixView};
33use thiserror::Error;
34
35use crate::utils;
36
37pub unsafe trait Repr: Copy {
60 type Row<'a>
62 where
63 Self: 'a;
64
65 fn nrows(&self) -> usize;
72
73 fn layout(&self) -> Result<Layout, LayoutError>;
81
82 unsafe fn get_row<'a>(self, ptr: NonNull<u8>, i: usize) -> Self::Row<'a>;
94}
95
96pub unsafe trait ReprMut: Repr {
114 type RowMut<'a>
116 where
117 Self: 'a;
118
119 unsafe fn get_row_mut<'a>(self, ptr: NonNull<u8>, i: usize) -> Self::RowMut<'a>;
130}
131
132pub unsafe trait ReprOwned: ReprMut {
142 unsafe fn drop(self, ptr: NonNull<u8>);
150}
151
152#[derive(Debug, Clone, Copy)]
158#[non_exhaustive]
159pub struct LayoutError;
160
161impl LayoutError {
162 pub fn new() -> Self {
164 Self
165 }
166}
167
168impl Default for LayoutError {
169 fn default() -> Self {
170 Self::new()
171 }
172}
173
174impl std::fmt::Display for LayoutError {
175 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
176 write!(f, "LayoutError")
177 }
178}
179
180impl std::error::Error for LayoutError {}
181
182impl From<std::alloc::LayoutError> for LayoutError {
183 fn from(_: std::alloc::LayoutError) -> Self {
184 LayoutError
185 }
186}
187
188pub unsafe trait NewRef<T>: Repr {
199 type Error;
201
202 fn new_ref(self, slice: &[T]) -> Result<MatRef<'_, Self>, Self::Error>;
204}
205
206pub unsafe trait NewMut<T>: ReprMut {
213 type Error;
215
216 fn new_mut(self, slice: &mut [T]) -> Result<MatMut<'_, Self>, Self::Error>;
218}
219
220pub unsafe trait NewOwned<T>: ReprOwned {
227 type Error;
229
230 fn new_owned(self, init: T) -> Result<Mat<Self>, Self::Error>;
232}
233
234#[derive(Debug, Clone, Copy)]
245pub struct Defaulted;
246
247pub trait NewCloned: ReprOwned {
249 fn new_cloned(v: MatRef<'_, Self>) -> Mat<Self>;
253}
254
255#[derive(Debug, Clone, Copy, PartialEq, Eq)]
269pub struct Standard<T> {
270 nrows: usize,
271 ncols: usize,
272 _elem: PhantomData<T>,
273}
274
275impl<T: Copy> Standard<T> {
276 pub fn new(nrows: usize, ncols: usize) -> Result<Self, Overflow> {
285 Overflow::check::<T>(nrows, ncols)?;
286 Ok(Self {
287 nrows,
288 ncols,
289 _elem: PhantomData,
290 })
291 }
292
293 pub fn num_elements(&self) -> usize {
295 self.nrows() * self.ncols()
297 }
298
299 fn nrows(&self) -> usize {
301 self.nrows
302 }
303
304 fn ncols(&self) -> usize {
306 self.ncols
307 }
308
309 fn check_slice(&self, slice: &[T]) -> Result<(), SliceError> {
314 let len = self.num_elements();
315
316 if slice.len() != len {
317 Err(SliceError::LengthMismatch {
318 expected: len,
319 found: slice.len(),
320 })
321 } else {
322 Ok(())
323 }
324 }
325
326 unsafe fn box_to_mat(self, b: Box<[T]>) -> Mat<Self> {
332 debug_assert_eq!(b.len(), self.num_elements(), "safety contract violated");
333
334 let ptr = utils::box_into_nonnull(b).cast::<u8>();
335
336 unsafe { Mat::from_raw_parts(self, ptr) }
340 }
341}
342
343#[derive(Debug, Clone, Copy)]
345pub struct Overflow {
346 nrows: usize,
347 ncols: usize,
348 elsize: usize,
349}
350
351impl Overflow {
352 pub(crate) fn for_type<T>(nrows: usize, ncols: usize) -> Self {
354 Self {
355 nrows,
356 ncols,
357 elsize: std::mem::size_of::<T>(),
358 }
359 }
360
361 pub(crate) fn check_byte_budget<T>(
367 capacity: usize,
368 nrows: usize,
369 ncols: usize,
370 ) -> Result<(), Self> {
371 let bytes = std::mem::size_of::<T>().saturating_mul(capacity);
372 if bytes <= isize::MAX as usize {
373 Ok(())
374 } else {
375 Err(Self::for_type::<T>(nrows, ncols))
376 }
377 }
378
379 pub(crate) fn check<T>(nrows: usize, ncols: usize) -> Result<(), Self> {
380 let capacity = nrows
382 .checked_mul(ncols)
383 .ok_or_else(|| Self::for_type::<T>(nrows, ncols))?;
384
385 Self::check_byte_budget::<T>(capacity, nrows, ncols)
386 }
387}
388
389impl std::fmt::Display for Overflow {
390 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
391 if self.elsize == 0 {
392 write!(
393 f,
394 "ZST matrix with dimensions {} x {} has more than `usize::MAX` elements",
395 self.nrows, self.ncols,
396 )
397 } else {
398 write!(
399 f,
400 "a matrix of size {} x {} with element size {} would exceed isize::MAX bytes",
401 self.nrows, self.ncols, self.elsize,
402 )
403 }
404 }
405}
406
407impl std::error::Error for Overflow {}
408
409#[derive(Debug, Clone, Copy, Error)]
411#[non_exhaustive]
412pub enum SliceError {
413 #[error("Length mismatch: expected {expected}, found {found}")]
414 LengthMismatch { expected: usize, found: usize },
415}
416
417unsafe impl<T: Copy> Repr for Standard<T> {
421 type Row<'a>
422 = &'a [T]
423 where
424 T: 'a;
425
426 fn nrows(&self) -> usize {
427 self.nrows
428 }
429
430 fn layout(&self) -> Result<Layout, LayoutError> {
431 Ok(Layout::array::<T>(self.num_elements())?)
432 }
433
434 unsafe fn get_row<'a>(self, ptr: NonNull<u8>, i: usize) -> Self::Row<'a> {
435 debug_assert!(ptr.cast::<T>().is_aligned());
436 debug_assert!(i < self.nrows);
437
438 let row_ptr = unsafe { ptr.as_ptr().cast::<T>().add(i * self.ncols) };
442
443 unsafe { std::slice::from_raw_parts(row_ptr, self.ncols) }
445 }
446}
447
448unsafe impl<T: Copy> ReprMut for Standard<T> {
451 type RowMut<'a>
452 = &'a mut [T]
453 where
454 T: 'a;
455
456 unsafe fn get_row_mut<'a>(self, ptr: NonNull<u8>, i: usize) -> Self::RowMut<'a> {
457 debug_assert!(ptr.cast::<T>().is_aligned());
458 debug_assert!(i < self.nrows);
459
460 let row_ptr = unsafe { ptr.as_ptr().cast::<T>().add(i * self.ncols) };
464
465 unsafe { std::slice::from_raw_parts_mut(row_ptr, self.ncols) }
468 }
469}
470
471unsafe impl<T: Copy> ReprOwned for Standard<T> {
475 unsafe fn drop(self, ptr: NonNull<u8>) {
476 unsafe {
482 let slice_ptr = std::ptr::slice_from_raw_parts_mut(
483 ptr.cast::<T>().as_ptr(),
484 self.nrows * self.ncols,
485 );
486 let _ = Box::from_raw(slice_ptr);
487 }
488 }
489}
490
491unsafe impl<T> NewOwned<T> for Standard<T>
494where
495 T: Copy,
496{
497 type Error = crate::error::Infallible;
498 fn new_owned(self, value: T) -> Result<Mat<Self>, Self::Error> {
499 let b: Box<[T]> = (0..self.num_elements()).map(|_| value).collect();
500
501 Ok(unsafe { self.box_to_mat(b) })
503 }
504}
505
506unsafe impl<T> NewOwned<Defaulted> for Standard<T>
508where
509 T: Copy + Default,
510{
511 type Error = crate::error::Infallible;
512 fn new_owned(self, _: Defaulted) -> Result<Mat<Self>, Self::Error> {
513 self.new_owned(T::default())
514 }
515}
516
517unsafe impl<T> NewRef<T> for Standard<T>
520where
521 T: Copy,
522{
523 type Error = SliceError;
524 fn new_ref(self, data: &[T]) -> Result<MatRef<'_, Self>, Self::Error> {
525 self.check_slice(data)?;
526
527 Ok(unsafe { MatRef::from_raw_parts(self, utils::as_nonnull(data).cast::<u8>()) })
532 }
533}
534
535unsafe impl<T> NewMut<T> for Standard<T>
538where
539 T: Copy,
540{
541 type Error = SliceError;
542 fn new_mut(self, data: &mut [T]) -> Result<MatMut<'_, Self>, Self::Error> {
543 self.check_slice(data)?;
544
545 Ok(unsafe { MatMut::from_raw_parts(self, utils::as_nonnull_mut(data).cast::<u8>()) })
550 }
551}
552
553impl<T> NewCloned for Standard<T>
554where
555 T: Copy,
556{
557 fn new_cloned(v: MatRef<'_, Self>) -> Mat<Self> {
558 let b: Box<[T]> = v.rows().flatten().copied().collect();
559
560 unsafe { v.repr().box_to_mat(b) }
562 }
563}
564
565#[derive(Debug)]
574pub struct Mat<T: ReprOwned> {
575 ptr: NonNull<u8>,
576 repr: T,
577 _invariant: PhantomData<fn(T) -> T>,
578}
579
580unsafe impl<T> Send for Mat<T> where T: ReprOwned + Send {}
582
583unsafe impl<T> Sync for Mat<T> where T: ReprOwned + Sync {}
585
586impl<T: ReprOwned> Mat<T> {
587 pub fn new<U>(repr: T, init: U) -> Result<Self, <T as NewOwned<U>>::Error>
589 where
590 T: NewOwned<U>,
591 {
592 repr.new_owned(init)
593 }
594
595 #[inline]
597 pub fn num_vectors(&self) -> usize {
598 self.repr.nrows()
599 }
600
601 pub fn repr(&self) -> &T {
603 &self.repr
604 }
605
606 #[must_use]
608 pub fn get_row(&self, i: usize) -> Option<T::Row<'_>> {
609 if i < self.num_vectors() {
610 let row = unsafe { self.get_row_unchecked(i) };
613 Some(row)
614 } else {
615 None
616 }
617 }
618
619 pub(crate) unsafe fn get_row_unchecked(&self, i: usize) -> T::Row<'_> {
620 unsafe { self.repr.get_row(self.ptr, i) }
623 }
624
625 #[must_use]
627 pub fn get_row_mut(&mut self, i: usize) -> Option<T::RowMut<'_>> {
628 if i < self.num_vectors() {
629 Some(unsafe { self.get_row_mut_unchecked(i) })
631 } else {
632 None
633 }
634 }
635
636 pub(crate) unsafe fn get_row_mut_unchecked(&mut self, i: usize) -> T::RowMut<'_> {
637 unsafe { self.repr.get_row_mut(self.ptr, i) }
640 }
641
642 #[inline]
644 pub fn as_view(&self) -> MatRef<'_, T> {
645 MatRef {
646 ptr: self.ptr,
647 repr: self.repr,
648 _lifetime: PhantomData,
649 }
650 }
651
652 #[inline]
654 pub fn as_view_mut(&mut self) -> MatMut<'_, T> {
655 MatMut {
656 ptr: self.ptr,
657 repr: self.repr,
658 _lifetime: PhantomData,
659 }
660 }
661
662 pub fn rows(&self) -> Rows<'_, T> {
664 Rows::new(self.reborrow())
665 }
666
667 pub fn rows_mut(&mut self) -> RowsMut<'_, T> {
669 RowsMut::new(self.reborrow_mut())
670 }
671
672 pub(crate) unsafe fn from_raw_parts(repr: T, ptr: NonNull<u8>) -> Self {
682 Self {
683 ptr,
684 repr,
685 _invariant: PhantomData,
686 }
687 }
688
689 pub fn as_raw_ptr(&self) -> *const u8 {
691 self.ptr.as_ptr()
692 }
693
694 pub(crate) fn as_raw_mut_ptr(&mut self) -> *mut u8 {
696 self.ptr.as_ptr()
697 }
698}
699
700impl<T: ReprOwned> Drop for Mat<T> {
701 fn drop(&mut self) {
702 unsafe { self.repr.drop(self.ptr) };
705 }
706}
707
708impl<T: NewCloned> Clone for Mat<T> {
709 fn clone(&self) -> Self {
710 T::new_cloned(self.as_view())
711 }
712}
713
714impl<T: Copy> Mat<Standard<T>> {
715 pub fn from_fn<F: FnMut() -> T>(repr: Standard<T>, mut f: F) -> Self {
717 let b: Box<[T]> = (0..repr.num_elements()).map(|_| f()).collect();
718 unsafe { repr.box_to_mat(b) }
720 }
721
722 #[inline]
724 pub fn vector_dim(&self) -> usize {
725 self.repr.ncols()
726 }
727
728 #[inline]
732 pub fn as_slice(&self) -> &[T] {
733 self.as_view().as_slice()
734 }
735
736 #[inline]
738 pub fn as_matrix_view(&self) -> MatrixView<'_, T> {
739 self.as_view().as_matrix_view()
740 }
741}
742
743#[derive(Debug, Clone, Copy)]
759pub struct MatRef<'a, T: Repr> {
760 ptr: NonNull<u8>,
761 repr: T,
762 _lifetime: PhantomData<&'a T>,
764}
765
766unsafe impl<T> Send for MatRef<'_, T> where T: Repr + Send {}
768
769unsafe impl<T> Sync for MatRef<'_, T> where T: Repr + Sync {}
771
772impl<'a, T: Repr> MatRef<'a, T> {
773 pub fn new<U>(repr: T, data: &'a [U]) -> Result<Self, T::Error>
775 where
776 T: NewRef<U>,
777 {
778 repr.new_ref(data)
779 }
780
781 #[inline]
783 pub fn num_vectors(&self) -> usize {
784 self.repr.nrows()
785 }
786
787 pub fn repr(&self) -> &T {
789 &self.repr
790 }
791
792 #[must_use]
794 pub fn get_row(&self, i: usize) -> Option<T::Row<'_>> {
795 if i < self.num_vectors() {
796 let row = unsafe { self.get_row_unchecked(i) };
799 Some(row)
800 } else {
801 None
802 }
803 }
804
805 #[inline]
811 pub(crate) unsafe fn get_row_unchecked(&self, i: usize) -> T::Row<'_> {
812 unsafe { self.repr.get_row(self.ptr, i) }
814 }
815
816 pub fn rows(&self) -> Rows<'_, T> {
818 Rows::new(*self)
819 }
820
821 pub fn to_owned(&self) -> Mat<T>
823 where
824 T: NewCloned,
825 {
826 T::new_cloned(*self)
827 }
828
829 pub unsafe fn from_raw_parts(repr: T, ptr: NonNull<u8>) -> Self {
837 Self {
838 ptr,
839 repr,
840 _lifetime: PhantomData,
841 }
842 }
843
844 pub fn as_raw_ptr(&self) -> *const u8 {
846 self.ptr.as_ptr()
847 }
848}
849
850impl<'a, T: Copy> MatRef<'a, Standard<T>> {
851 #[inline]
853 pub fn vector_dim(&self) -> usize {
854 self.repr.ncols()
855 }
856
857 #[inline]
861 pub fn as_slice(&self) -> &'a [T] {
862 let len = self.repr.num_elements();
863 unsafe { std::slice::from_raw_parts(self.ptr.as_ptr().cast::<T>(), len) }
866 }
867
868 #[allow(clippy::expect_used)]
870 #[inline]
871 pub fn as_matrix_view(&self) -> MatrixView<'a, T> {
872 MatrixView::try_from(self.as_slice(), self.num_vectors(), self.vector_dim())
875 .expect("Standard<T> has valid dimensions")
876 }
877}
878
879impl<'this, T: ReprOwned> Reborrow<'this> for Mat<T> {
881 type Target = MatRef<'this, T>;
882
883 fn reborrow(&'this self) -> Self::Target {
884 self.as_view()
885 }
886}
887
888impl<'this, T: ReprOwned> ReborrowMut<'this> for Mat<T> {
890 type Target = MatMut<'this, T>;
891
892 fn reborrow_mut(&'this mut self) -> Self::Target {
893 self.as_view_mut()
894 }
895}
896
897impl<'this, 'a, T: Repr> Reborrow<'this> for MatRef<'a, T> {
899 type Target = MatRef<'this, T>;
900
901 fn reborrow(&'this self) -> Self::Target {
902 MatRef {
903 ptr: self.ptr,
904 repr: self.repr,
905 _lifetime: PhantomData,
906 }
907 }
908}
909
910#[derive(Debug)]
927pub struct MatMut<'a, T: ReprMut> {
928 ptr: NonNull<u8>,
929 repr: T,
930 _lifetime: PhantomData<&'a mut T>,
932}
933
934unsafe impl<T> Send for MatMut<'_, T> where T: ReprMut + Send {}
936
937unsafe impl<T> Sync for MatMut<'_, T> where T: ReprMut + Sync {}
939
940impl<'a, T: ReprMut> MatMut<'a, T> {
941 pub fn new<U>(repr: T, data: &'a mut [U]) -> Result<Self, T::Error>
943 where
944 T: NewMut<U>,
945 {
946 repr.new_mut(data)
947 }
948
949 #[inline]
951 pub fn num_vectors(&self) -> usize {
952 self.repr.nrows()
953 }
954
955 pub fn repr(&self) -> &T {
957 &self.repr
958 }
959
960 #[inline]
962 #[must_use]
963 pub fn get_row(&self, i: usize) -> Option<T::Row<'_>> {
964 if i < self.num_vectors() {
965 Some(unsafe { self.get_row_unchecked(i) })
967 } else {
968 None
969 }
970 }
971
972 #[inline]
978 pub(crate) unsafe fn get_row_unchecked(&self, i: usize) -> T::Row<'_> {
979 unsafe { self.repr.get_row(self.ptr, i) }
981 }
982
983 #[inline]
985 #[must_use]
986 pub fn get_row_mut(&mut self, i: usize) -> Option<T::RowMut<'_>> {
987 if i < self.num_vectors() {
988 Some(unsafe { self.get_row_mut_unchecked(i) })
990 } else {
991 None
992 }
993 }
994
995 #[inline]
1001 pub(crate) unsafe fn get_row_mut_unchecked(&mut self, i: usize) -> T::RowMut<'_> {
1002 unsafe { self.repr.get_row_mut(self.ptr, i) }
1005 }
1006
1007 pub fn as_view(&self) -> MatRef<'_, T> {
1009 MatRef {
1010 ptr: self.ptr,
1011 repr: self.repr,
1012 _lifetime: PhantomData,
1013 }
1014 }
1015
1016 pub fn rows(&self) -> Rows<'_, T> {
1018 Rows::new(self.reborrow())
1019 }
1020
1021 pub fn rows_mut(&mut self) -> RowsMut<'_, T> {
1023 RowsMut::new(self.reborrow_mut())
1024 }
1025
1026 pub fn to_owned(&self) -> Mat<T>
1028 where
1029 T: NewCloned,
1030 {
1031 T::new_cloned(self.as_view())
1032 }
1033
1034 pub unsafe fn from_raw_parts(repr: T, ptr: NonNull<u8>) -> Self {
1041 Self {
1042 ptr,
1043 repr,
1044 _lifetime: PhantomData,
1045 }
1046 }
1047
1048 pub fn as_raw_ptr(&self) -> *const u8 {
1050 self.ptr.as_ptr()
1051 }
1052
1053 pub(crate) fn as_raw_mut_ptr(&mut self) -> *mut u8 {
1055 self.ptr.as_ptr()
1056 }
1057}
1058
1059impl<'this, 'a, T: ReprMut> Reborrow<'this> for MatMut<'a, T> {
1061 type Target = MatRef<'this, T>;
1062
1063 fn reborrow(&'this self) -> Self::Target {
1064 self.as_view()
1065 }
1066}
1067
1068impl<'this, 'a, T: ReprMut> ReborrowMut<'this> for MatMut<'a, T> {
1070 type Target = MatMut<'this, T>;
1071
1072 fn reborrow_mut(&'this mut self) -> Self::Target {
1073 MatMut {
1074 ptr: self.ptr,
1075 repr: self.repr,
1076 _lifetime: PhantomData,
1077 }
1078 }
1079}
1080
1081impl<'a, T: Copy> MatMut<'a, Standard<T>> {
1082 #[inline]
1084 pub fn vector_dim(&self) -> usize {
1085 self.repr.ncols()
1086 }
1087
1088 #[inline]
1092 pub fn as_slice(&self) -> &[T] {
1093 self.as_view().as_slice()
1094 }
1095
1096 #[inline]
1098 pub fn as_matrix_view(&self) -> MatrixView<'_, T> {
1099 self.as_view().as_matrix_view()
1100 }
1101}
1102
1103#[derive(Debug)]
1111pub struct Rows<'a, T: Repr> {
1112 matrix: MatRef<'a, T>,
1113 current: usize,
1114}
1115
1116impl<'a, T> Rows<'a, T>
1117where
1118 T: Repr,
1119{
1120 fn new(matrix: MatRef<'a, T>) -> Self {
1121 Self { matrix, current: 0 }
1122 }
1123}
1124
1125impl<'a, T> Iterator for Rows<'a, T>
1126where
1127 T: Repr + 'a,
1128{
1129 type Item = T::Row<'a>;
1130
1131 fn next(&mut self) -> Option<Self::Item> {
1132 let current = self.current;
1133 if current >= self.matrix.num_vectors() {
1134 None
1135 } else {
1136 self.current += 1;
1137 Some(unsafe { self.matrix.repr.get_row(self.matrix.ptr, current) })
1143 }
1144 }
1145
1146 fn size_hint(&self) -> (usize, Option<usize>) {
1147 let remaining = self.matrix.num_vectors() - self.current;
1148 (remaining, Some(remaining))
1149 }
1150}
1151
1152impl<'a, T> ExactSizeIterator for Rows<'a, T> where T: Repr + 'a {}
1153impl<'a, T> FusedIterator for Rows<'a, T> where T: Repr + 'a {}
1154
1155#[derive(Debug)]
1163pub struct RowsMut<'a, T: ReprMut> {
1164 matrix: MatMut<'a, T>,
1165 current: usize,
1166}
1167
1168impl<'a, T> RowsMut<'a, T>
1169where
1170 T: ReprMut,
1171{
1172 fn new(matrix: MatMut<'a, T>) -> Self {
1173 Self { matrix, current: 0 }
1174 }
1175}
1176
1177impl<'a, T> Iterator for RowsMut<'a, T>
1178where
1179 T: ReprMut + 'a,
1180{
1181 type Item = T::RowMut<'a>;
1182
1183 fn next(&mut self) -> Option<Self::Item> {
1184 let current = self.current;
1185 if current >= self.matrix.num_vectors() {
1186 None
1187 } else {
1188 self.current += 1;
1189 Some(unsafe { self.matrix.repr.get_row_mut(self.matrix.ptr, current) })
1198 }
1199 }
1200
1201 fn size_hint(&self) -> (usize, Option<usize>) {
1202 let remaining = self.matrix.num_vectors() - self.current;
1203 (remaining, Some(remaining))
1204 }
1205}
1206
1207impl<'a, T> ExactSizeIterator for RowsMut<'a, T> where T: ReprMut + 'a {}
1208impl<'a, T> FusedIterator for RowsMut<'a, T> where T: ReprMut + 'a {}
1209
1210#[cfg(test)]
1215mod tests {
1216 use super::*;
1217
1218 use std::fmt::Display;
1219
1220 use diskann_utils::lazy_format;
1221
1222 fn assert_copy<T: Copy>(_: &T) {}
1224
1225 fn _assert_matref_covariant_lifetime<'long: 'short, 'short, T: Repr>(
1235 v: MatRef<'long, T>,
1236 ) -> MatRef<'short, T> {
1237 v
1238 }
1239
1240 fn _assert_matref_covariant_repr<'long: 'short, 'short, 'a>(
1242 v: MatRef<'a, Standard<&'long u8>>,
1243 ) -> MatRef<'a, Standard<&'short u8>> {
1244 v
1245 }
1246
1247 fn _assert_matmut_covariant_lifetime<'long: 'short, 'short, T: ReprMut>(
1249 v: MatMut<'long, T>,
1250 ) -> MatMut<'short, T> {
1251 v
1252 }
1253
1254 fn edge_cases(nrows: usize) -> Vec<usize> {
1255 let max = usize::MAX;
1256
1257 vec![
1258 nrows,
1259 nrows + 1,
1260 nrows + 11,
1261 nrows + 20,
1262 max / 2,
1263 max.div_ceil(2),
1264 max - 1,
1265 max,
1266 ]
1267 }
1268
1269 fn fill_mat(x: &mut Mat<Standard<usize>>, repr: Standard<usize>) {
1270 assert_eq!(x.repr(), &repr);
1271 assert_eq!(x.num_vectors(), repr.nrows());
1272 assert_eq!(x.vector_dim(), repr.ncols());
1273
1274 for i in 0..x.num_vectors() {
1275 let row = x.get_row_mut(i).unwrap();
1276 assert_eq!(row.len(), repr.ncols());
1277 row.iter_mut()
1278 .enumerate()
1279 .for_each(|(j, r)| *r = 10 * i + j);
1280 }
1281
1282 for i in edge_cases(repr.nrows()).into_iter() {
1283 assert!(x.get_row_mut(i).is_none());
1284 }
1285 }
1286
1287 fn fill_mat_mut(mut x: MatMut<'_, Standard<usize>>, repr: Standard<usize>) {
1288 assert_eq!(x.repr(), &repr);
1289 assert_eq!(x.num_vectors(), repr.nrows());
1290 assert_eq!(x.vector_dim(), repr.ncols());
1291
1292 for i in 0..x.num_vectors() {
1293 let row = x.get_row_mut(i).unwrap();
1294 assert_eq!(row.len(), repr.ncols());
1295
1296 row.iter_mut()
1297 .enumerate()
1298 .for_each(|(j, r)| *r = 10 * i + j);
1299 }
1300
1301 for i in edge_cases(repr.nrows()).into_iter() {
1302 assert!(x.get_row_mut(i).is_none());
1303 }
1304 }
1305
1306 fn fill_rows_mut(x: RowsMut<'_, Standard<usize>>, repr: Standard<usize>) {
1307 assert_eq!(x.len(), repr.nrows());
1308 let mut all_rows: Vec<_> = x.collect();
1310 assert_eq!(all_rows.len(), repr.nrows());
1311 for (i, row) in all_rows.iter_mut().enumerate() {
1312 assert_eq!(row.len(), repr.ncols());
1313 row.iter_mut()
1314 .enumerate()
1315 .for_each(|(j, r)| *r = 10 * i + j);
1316 }
1317 }
1318
1319 fn check_mat(x: &Mat<Standard<usize>>, repr: Standard<usize>, ctx: &dyn Display) {
1320 assert_eq!(x.repr(), &repr);
1321 assert_eq!(x.num_vectors(), repr.nrows());
1322 assert_eq!(x.vector_dim(), repr.ncols());
1323
1324 for i in 0..x.num_vectors() {
1325 let row = x.get_row(i).unwrap();
1326
1327 assert_eq!(row.len(), repr.ncols(), "ctx: {ctx}");
1328 row.iter().enumerate().for_each(|(j, r)| {
1329 assert_eq!(
1330 *r,
1331 10 * i + j,
1332 "mismatched entry at row {}, col {} -- ctx: {}",
1333 i,
1334 j,
1335 ctx
1336 )
1337 });
1338 }
1339
1340 for i in edge_cases(repr.nrows()).into_iter() {
1341 assert!(x.get_row(i).is_none(), "ctx: {ctx}");
1342 }
1343 }
1344
1345 fn check_mat_ref(x: MatRef<'_, Standard<usize>>, repr: Standard<usize>, ctx: &dyn Display) {
1346 assert_eq!(x.repr(), &repr);
1347 assert_eq!(x.num_vectors(), repr.nrows());
1348 assert_eq!(x.vector_dim(), repr.ncols());
1349
1350 assert_copy(&x);
1351 for i in 0..x.num_vectors() {
1352 let row = x.get_row(i).unwrap();
1353 assert_eq!(row.len(), repr.ncols(), "ctx: {ctx}");
1354
1355 row.iter().enumerate().for_each(|(j, r)| {
1356 assert_eq!(
1357 *r,
1358 10 * i + j,
1359 "mismatched entry at row {}, col {} -- ctx: {}",
1360 i,
1361 j,
1362 ctx
1363 )
1364 });
1365 }
1366
1367 for i in edge_cases(repr.nrows()).into_iter() {
1368 assert!(x.get_row(i).is_none(), "ctx: {ctx}");
1369 }
1370 }
1371
1372 fn check_mat_mut(x: MatMut<'_, Standard<usize>>, repr: Standard<usize>, ctx: &dyn Display) {
1373 assert_eq!(x.repr(), &repr);
1374 assert_eq!(x.num_vectors(), repr.nrows());
1375 assert_eq!(x.vector_dim(), repr.ncols());
1376
1377 for i in 0..x.num_vectors() {
1378 let row = x.get_row(i).unwrap();
1379 assert_eq!(row.len(), repr.ncols(), "ctx: {ctx}");
1380
1381 row.iter().enumerate().for_each(|(j, r)| {
1382 assert_eq!(
1383 *r,
1384 10 * i + j,
1385 "mismatched entry at row {}, col {} -- ctx: {}",
1386 i,
1387 j,
1388 ctx
1389 )
1390 });
1391 }
1392
1393 for i in edge_cases(repr.nrows()).into_iter() {
1394 assert!(x.get_row(i).is_none(), "ctx: {ctx}");
1395 }
1396 }
1397
1398 fn check_rows(x: Rows<'_, Standard<usize>>, repr: Standard<usize>, ctx: &dyn Display) {
1399 assert_eq!(x.len(), repr.nrows(), "ctx: {ctx}");
1400 let all_rows: Vec<_> = x.collect();
1401 assert_eq!(all_rows.len(), repr.nrows(), "ctx: {ctx}");
1402 for (i, row) in all_rows.iter().enumerate() {
1403 assert_eq!(row.len(), repr.ncols(), "ctx: {ctx}");
1404 row.iter().enumerate().for_each(|(j, r)| {
1405 assert_eq!(
1406 *r,
1407 10 * i + j,
1408 "mismatched entry at row {}, col {} -- ctx: {}",
1409 i,
1410 j,
1411 ctx
1412 )
1413 });
1414 }
1415 }
1416
1417 #[test]
1422 fn standard_representation() {
1423 let repr = Standard::<f32>::new(4, 3).unwrap();
1424 assert_eq!(repr.nrows(), 4);
1425 assert_eq!(repr.ncols(), 3);
1426
1427 let layout = repr.layout().unwrap();
1428 assert_eq!(layout.size(), 4 * 3 * std::mem::size_of::<f32>());
1429 assert_eq!(layout.align(), std::mem::align_of::<f32>());
1430 }
1431
1432 #[test]
1433 fn standard_zero_dimensions() {
1434 for (nrows, ncols) in [(0, 0), (0, 5), (5, 0)] {
1435 let repr = Standard::<u8>::new(nrows, ncols).unwrap();
1436 assert_eq!(repr.nrows(), nrows);
1437 assert_eq!(repr.ncols(), ncols);
1438 let layout = repr.layout().unwrap();
1439 assert_eq!(layout.size(), 0);
1440 }
1441 }
1442
1443 #[test]
1444 fn standard_check_slice() {
1445 let repr = Standard::<u32>::new(3, 4).unwrap();
1446
1447 let data = vec![0u32; 12];
1449 assert!(repr.check_slice(&data).is_ok());
1450
1451 let short = vec![0u32; 11];
1453 assert!(matches!(
1454 repr.check_slice(&short),
1455 Err(SliceError::LengthMismatch {
1456 expected: 12,
1457 found: 11
1458 })
1459 ));
1460
1461 let long = vec![0u32; 13];
1463 assert!(matches!(
1464 repr.check_slice(&long),
1465 Err(SliceError::LengthMismatch {
1466 expected: 12,
1467 found: 13
1468 })
1469 ));
1470
1471 let overflow_repr = Standard::<u8>::new(usize::MAX, 2).unwrap_err();
1473 assert!(matches!(overflow_repr, Overflow { .. }));
1474 }
1475
1476 #[test]
1477 fn standard_new_rejects_element_count_overflow() {
1478 assert!(Standard::<u8>::new(usize::MAX, 2).is_err());
1480 assert!(Standard::<u8>::new(2, usize::MAX).is_err());
1481 assert!(Standard::<u8>::new(usize::MAX, usize::MAX).is_err());
1482 }
1483
1484 #[test]
1485 fn standard_new_rejects_byte_count_exceeding_isize_max() {
1486 let half = (isize::MAX as usize / std::mem::size_of::<u64>()) + 1;
1488 assert!(Standard::<u64>::new(half, 1).is_err());
1489 assert!(Standard::<u64>::new(1, half).is_err());
1490 }
1491
1492 #[test]
1493 fn standard_new_accepts_boundary_below_isize_max() {
1494 let max_elems = isize::MAX as usize / std::mem::size_of::<u64>();
1496 let repr = Standard::<u64>::new(max_elems, 1).unwrap();
1497 assert_eq!(repr.num_elements(), max_elems);
1498 }
1499
1500 #[test]
1501 fn standard_new_zst_rejects_element_count_overflow() {
1502 assert!(Standard::<()>::new(usize::MAX, 2).is_err());
1505 assert!(Standard::<()>::new(usize::MAX / 2 + 1, 3).is_err());
1506 }
1507
1508 #[test]
1509 fn standard_new_zst_accepts_large_non_overflowing() {
1510 let repr = Standard::<()>::new(usize::MAX, 1).unwrap();
1512 assert_eq!(repr.num_elements(), usize::MAX);
1513 assert_eq!(repr.layout().unwrap().size(), 0);
1514 }
1515
1516 #[test]
1517 fn standard_new_overflow_error_display() {
1518 let err = Standard::<u32>::new(usize::MAX, 2).unwrap_err();
1519 let msg = err.to_string();
1520 assert!(msg.contains("would exceed isize::MAX bytes"), "{msg}");
1521
1522 let zst_err = Standard::<()>::new(usize::MAX, 2).unwrap_err();
1523 let zst_msg = zst_err.to_string();
1524 assert!(zst_msg.contains("ZST matrix"), "{zst_msg}");
1525 assert!(zst_msg.contains("usize::MAX"), "{zst_msg}");
1526 }
1527
1528 #[test]
1533 fn mat_new_and_basic_accessors() {
1534 let mat = Mat::new(Standard::<usize>::new(3, 4).unwrap(), 42usize).unwrap();
1535 let base: *const u8 = mat.as_raw_ptr();
1536
1537 assert_eq!(mat.num_vectors(), 3);
1538 assert_eq!(mat.vector_dim(), 4);
1539
1540 let repr = mat.repr();
1541 assert_eq!(repr.nrows(), 3);
1542 assert_eq!(repr.ncols(), 4);
1543
1544 for (i, r) in mat.rows().enumerate() {
1545 assert_eq!(r, &[42, 42, 42, 42]);
1546 let ptr = r.as_ptr().cast::<u8>();
1547 assert_eq!(
1548 ptr,
1549 base.wrapping_add(std::mem::size_of::<usize>() * mat.repr().ncols() * i),
1550 );
1551 }
1552 }
1553
1554 #[test]
1555 fn mat_new_with_default() {
1556 let mat = Mat::new(Standard::<usize>::new(2, 3).unwrap(), Defaulted).unwrap();
1557 let base: *const u8 = mat.as_raw_ptr();
1558
1559 assert_eq!(mat.num_vectors(), 2);
1560 for (i, row) in mat.rows().enumerate() {
1561 assert!(row.iter().all(|&v| v == 0));
1562
1563 let ptr = row.as_ptr().cast::<u8>();
1564 assert_eq!(
1565 ptr,
1566 base.wrapping_add(std::mem::size_of::<usize>() * mat.repr().ncols() * i),
1567 );
1568 }
1569 }
1570
1571 const ROWS: &[usize] = &[0, 1, 2, 3, 5, 10];
1572 const COLS: &[usize] = &[0, 1, 2, 3, 5, 10];
1573
1574 #[test]
1575 fn test_mat() {
1576 for nrows in ROWS {
1577 for ncols in COLS {
1578 let repr = Standard::<usize>::new(*nrows, *ncols).unwrap();
1579 let ctx = &lazy_format!("nrows = {}, ncols = {}", nrows, ncols);
1580
1581 {
1583 let ctx = &lazy_format!("{ctx} - direct");
1584 let mut mat = Mat::new(repr, Defaulted).unwrap();
1585
1586 assert_eq!(mat.num_vectors(), *nrows);
1587 assert_eq!(mat.vector_dim(), *ncols);
1588
1589 fill_mat(&mut mat, repr);
1590
1591 check_mat(&mat, repr, ctx);
1592 check_mat_ref(mat.reborrow(), repr, ctx);
1593 check_mat_mut(mat.reborrow_mut(), repr, ctx);
1594 check_rows(mat.rows(), repr, ctx);
1595
1596 assert_eq!(mat.as_raw_ptr(), mat.reborrow().as_raw_ptr());
1598 assert_eq!(mat.as_raw_ptr(), mat.reborrow_mut().as_raw_ptr());
1599 }
1600
1601 {
1603 let ctx = &lazy_format!("{ctx} - matmut");
1604 let mut mat = Mat::new(repr, Defaulted).unwrap();
1605 let matmut = mat.reborrow_mut();
1606
1607 assert_eq!(matmut.num_vectors(), *nrows);
1608 assert_eq!(matmut.vector_dim(), *ncols);
1609
1610 fill_mat_mut(matmut, repr);
1611
1612 check_mat(&mat, repr, ctx);
1613 check_mat_ref(mat.reborrow(), repr, ctx);
1614 check_mat_mut(mat.reborrow_mut(), repr, ctx);
1615 check_rows(mat.rows(), repr, ctx);
1616 }
1617
1618 {
1620 let ctx = &lazy_format!("{ctx} - rows_mut");
1621 let mut mat = Mat::new(repr, Defaulted).unwrap();
1622 fill_rows_mut(mat.rows_mut(), repr);
1623
1624 check_mat(&mat, repr, ctx);
1625 check_mat_ref(mat.reborrow(), repr, ctx);
1626 check_mat_mut(mat.reborrow_mut(), repr, ctx);
1627 check_rows(mat.rows(), repr, ctx);
1628 }
1629 }
1630 }
1631 }
1632
1633 #[test]
1634 fn test_mat_clone() {
1635 for nrows in ROWS {
1636 for ncols in COLS {
1637 let repr = Standard::<usize>::new(*nrows, *ncols).unwrap();
1638 let ctx = &lazy_format!("nrows = {}, ncols = {}", nrows, ncols);
1639
1640 let mut mat = Mat::new(repr, Defaulted).unwrap();
1641 fill_mat(&mut mat, repr);
1642
1643 {
1645 let ctx = &lazy_format!("{ctx} - Mat::clone");
1646 let cloned = mat.clone();
1647
1648 assert_eq!(cloned.num_vectors(), *nrows);
1649 assert_eq!(cloned.vector_dim(), *ncols);
1650
1651 check_mat(&cloned, repr, ctx);
1652 check_mat_ref(cloned.reborrow(), repr, ctx);
1653 check_rows(cloned.rows(), repr, ctx);
1654
1655 if repr.num_elements() > 0 {
1657 assert_ne!(mat.as_raw_ptr(), cloned.as_raw_ptr());
1658 }
1659 }
1660
1661 {
1663 let ctx = &lazy_format!("{ctx} - MatRef::to_owned");
1664 let owned = mat.as_view().to_owned();
1665
1666 check_mat(&owned, repr, ctx);
1667 check_mat_ref(owned.reborrow(), repr, ctx);
1668 check_rows(owned.rows(), repr, ctx);
1669
1670 if repr.num_elements() > 0 {
1671 assert_ne!(mat.as_raw_ptr(), owned.as_raw_ptr());
1672 }
1673 }
1674
1675 {
1677 let ctx = &lazy_format!("{ctx} - MatMut::to_owned");
1678 let owned = mat.as_view_mut().to_owned();
1679
1680 check_mat(&owned, repr, ctx);
1681 check_mat_ref(owned.reborrow(), repr, ctx);
1682 check_rows(owned.rows(), repr, ctx);
1683
1684 if repr.num_elements() > 0 {
1685 assert_ne!(mat.as_raw_ptr(), owned.as_raw_ptr());
1686 }
1687 }
1688 }
1689 }
1690 }
1691
1692 #[test]
1693 fn test_mat_refmut() {
1694 for nrows in ROWS {
1695 for ncols in COLS {
1696 let repr = Standard::<usize>::new(*nrows, *ncols).unwrap();
1697 let ctx = &lazy_format!("nrows = {}, ncols = {}", nrows, ncols);
1698
1699 {
1701 let ctx = &lazy_format!("{ctx} - by matmut");
1702 let mut b: Box<[_]> = (0..repr.num_elements()).map(|_| 0usize).collect();
1703 let ptr = b.as_ptr().cast::<u8>();
1704 let mut matmut = MatMut::new(repr, &mut b).unwrap();
1705
1706 assert_eq!(
1707 ptr,
1708 matmut.as_raw_ptr(),
1709 "underlying memory should be preserved",
1710 );
1711
1712 fill_mat_mut(matmut.reborrow_mut(), repr);
1713
1714 check_mat_mut(matmut.reborrow_mut(), repr, ctx);
1715 check_mat_ref(matmut.reborrow(), repr, ctx);
1716 check_rows(matmut.rows(), repr, ctx);
1717 check_rows(matmut.reborrow().rows(), repr, ctx);
1718
1719 let matref = MatRef::new(repr, &b).unwrap();
1720 check_mat_ref(matref, repr, ctx);
1721 check_mat_ref(matref.reborrow(), repr, ctx);
1722 check_rows(matref.rows(), repr, ctx);
1723 }
1724
1725 {
1727 let ctx = &lazy_format!("{ctx} - by rows");
1728 let mut b: Box<[_]> = (0..repr.num_elements()).map(|_| 0usize).collect();
1729 let ptr = b.as_ptr().cast::<u8>();
1730 let mut matmut = MatMut::new(repr, &mut b).unwrap();
1731
1732 assert_eq!(
1733 ptr,
1734 matmut.as_raw_ptr(),
1735 "underlying memory should be preserved",
1736 );
1737
1738 fill_rows_mut(matmut.rows_mut(), repr);
1739
1740 check_mat_mut(matmut.reborrow_mut(), repr, ctx);
1741 check_mat_ref(matmut.reborrow(), repr, ctx);
1742 check_rows(matmut.rows(), repr, ctx);
1743 check_rows(matmut.reborrow().rows(), repr, ctx);
1744
1745 let matref = MatRef::new(repr, &b).unwrap();
1746 check_mat_ref(matref, repr, ctx);
1747 check_mat_ref(matref.reborrow(), repr, ctx);
1748 check_rows(matref.rows(), repr, ctx);
1749 }
1750 }
1751 }
1752 }
1753
1754 #[test]
1759 fn test_standard_new_owned() {
1760 let rows = [0, 1, 2, 3, 5, 10];
1761 let cols = [0, 1, 2, 3, 5, 10];
1762
1763 for nrows in rows {
1764 for ncols in cols {
1765 let m = Mat::new(Standard::new(nrows, ncols).unwrap(), 1usize).unwrap();
1766 let rows_iter = m.rows();
1767 let len = <_ as ExactSizeIterator>::len(&rows_iter);
1768 assert_eq!(len, nrows);
1769 for r in rows_iter {
1770 assert_eq!(r.len(), ncols);
1771 assert!(r.iter().all(|i| *i == 1usize));
1772 }
1773 }
1774 }
1775 }
1776
1777 #[test]
1778 fn test_mat_from_fn() {
1779 let rows = [0, 1, 2, 5];
1780 let cols = [0, 1, 3, 7];
1781
1782 for nrows in rows {
1783 for ncols in cols {
1784 let mut counter = 0u32;
1785 let m = Mat::from_fn(Standard::new(nrows, ncols).unwrap(), || {
1786 let v = counter;
1787 counter += 1;
1788 v
1789 });
1790
1791 assert_eq!(counter as usize, nrows * ncols);
1792 for (i, row) in m.rows().enumerate() {
1793 assert_eq!(row.len(), ncols);
1794 for (j, &v) in row.iter().enumerate() {
1795 assert_eq!(v, (i * ncols + j) as u32);
1796 }
1797 }
1798 }
1799 }
1800 }
1801
1802 #[test]
1803 fn matref_new_slice_length_error() {
1804 let repr = Standard::<u32>::new(3, 4).unwrap();
1805
1806 let data = vec![0u32; 12];
1808 assert!(MatRef::new(repr, &data).is_ok());
1809
1810 let short = vec![0u32; 11];
1812 assert!(matches!(
1813 MatRef::new(repr, &short),
1814 Err(SliceError::LengthMismatch {
1815 expected: 12,
1816 found: 11
1817 })
1818 ));
1819
1820 let long = vec![0u32; 13];
1822 assert!(matches!(
1823 MatRef::new(repr, &long),
1824 Err(SliceError::LengthMismatch {
1825 expected: 12,
1826 found: 13
1827 })
1828 ));
1829 }
1830
1831 #[test]
1832 fn matmut_new_slice_length_error() {
1833 let repr = Standard::<u32>::new(3, 4).unwrap();
1834
1835 let mut data = vec![0u32; 12];
1837 assert!(MatMut::new(repr, &mut data).is_ok());
1838
1839 let mut short = vec![0u32; 11];
1841 assert!(matches!(
1842 MatMut::new(repr, &mut short),
1843 Err(SliceError::LengthMismatch {
1844 expected: 12,
1845 found: 11
1846 })
1847 ));
1848
1849 let mut long = vec![0u32; 13];
1851 assert!(matches!(
1852 MatMut::new(repr, &mut long),
1853 Err(SliceError::LengthMismatch {
1854 expected: 12,
1855 found: 13
1856 })
1857 ));
1858 }
1859
1860 #[test]
1861 fn as_matrix_view_roundtrip() {
1862 let data = [1.0f32, 2.0, 3.0, 4.0, 5.0, 6.0];
1863
1864 let matref = MatRef::new(Standard::new(2, 3).unwrap(), &data).unwrap();
1866 let view = matref.as_matrix_view();
1867 assert_eq!(view.nrows(), 2);
1868 assert_eq!(view.ncols(), 3);
1869 for row in 0..2 {
1870 for col in 0..3 {
1871 assert_eq!(view[(row, col)], data[row * 3 + col]);
1872 }
1873 }
1874 assert_eq!(matref.as_slice(), &data);
1875
1876 let mut mat = Mat::new(Standard::<f32>::new(2, 3).unwrap(), 0.0f32).unwrap();
1878 for i in 0..2 {
1879 let r = mat.get_row_mut(i).unwrap();
1880 for j in 0..3 {
1881 r[j] = data[i * 3 + j];
1882 }
1883 }
1884 let view = mat.as_matrix_view();
1885 assert_eq!(view.nrows(), 2);
1886 assert_eq!(view.ncols(), 3);
1887 for row in 0..2 {
1888 for col in 0..3 {
1889 assert_eq!(view[(row, col)], data[row * 3 + col]);
1890 }
1891 }
1892 assert_eq!(mat.as_slice(), &data);
1893
1894 let mut buf = [1.0f32, 2.0, 3.0, 4.0, 5.0, 6.0];
1896 let matmut = MatMut::new(Standard::new(2, 3).unwrap(), &mut buf).unwrap();
1897 let view = matmut.as_matrix_view();
1898 assert_eq!(view.nrows(), 2);
1899 assert_eq!(view.ncols(), 3);
1900 for row in 0..2 {
1901 for col in 0..3 {
1902 assert_eq!(view[(row, col)], data[row * 3 + col]);
1903 }
1904 }
1905 assert_eq!(matmut.as_slice(), &data);
1906 }
1907}