1use std::{alloc::Layout, iter::FusedIterator, marker::PhantomData, ptr::NonNull};
31
32use diskann_utils::{Reborrow, ReborrowMut, views::rowmajor};
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>;
80
81 unsafe fn get_row<'a>(self, ptr: NonNull<u8>, i: usize) -> Self::Row<'a>;
93}
94
95pub unsafe trait ReprMut: Repr {
113 type RowMut<'a>
115 where
116 Self: 'a;
117
118 unsafe fn get_row_mut<'a>(self, ptr: NonNull<u8>, i: usize) -> Self::RowMut<'a>;
129}
130
131pub unsafe trait ReprOwned: ReprMut {
141 unsafe fn drop(self, ptr: NonNull<u8>);
149}
150
151#[derive(Debug, Clone, Copy)]
157#[non_exhaustive]
158pub struct LayoutError;
159
160impl LayoutError {
161 pub fn new() -> Self {
163 Self
164 }
165}
166
167impl Default for LayoutError {
168 fn default() -> Self {
169 Self::new()
170 }
171}
172
173impl std::fmt::Display for LayoutError {
174 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
175 write!(f, "LayoutError")
176 }
177}
178
179impl std::error::Error for LayoutError {}
180
181impl From<std::alloc::LayoutError> for LayoutError {
182 fn from(_: std::alloc::LayoutError) -> Self {
183 LayoutError
184 }
185}
186
187pub unsafe trait NewRef<T>: Repr {
198 type Error;
200
201 fn new_ref(self, slice: &[T]) -> Result<MatRef<'_, Self>, Self::Error>;
203}
204
205pub unsafe trait NewMut<T>: ReprMut {
212 type Error;
214
215 fn new_mut(self, slice: &mut [T]) -> Result<MatMut<'_, Self>, Self::Error>;
217}
218
219pub unsafe trait NewOwned<T>: ReprOwned {
226 type Error;
228
229 fn new_owned(self, init: T) -> Result<Mat<Self>, Self::Error>;
231}
232
233#[derive(Debug, Clone, Copy)]
244pub struct Defaulted;
245
246pub trait NewCloned: ReprOwned {
248 fn new_cloned(v: MatRef<'_, Self>) -> Mat<Self>;
252}
253
254#[derive(Debug)]
268pub struct Standard<T> {
269 nrows: usize,
270 ncols: usize,
271 _elem: PhantomData<T>,
272}
273
274impl<T> Copy for Standard<T> {}
278
279impl<T> Clone for Standard<T> {
280 fn clone(&self) -> Self {
281 *self
282 }
283}
284
285impl<T> PartialEq for Standard<T> {
286 fn eq(&self, other: &Self) -> bool {
287 self.nrows == other.nrows && self.ncols == other.ncols
288 }
289}
290
291impl<T> Eq for Standard<T> {}
292
293impl<T> Standard<T> {
294 pub fn new(nrows: usize, ncols: usize) -> Result<Self, Overflow> {
303 Overflow::check::<T>(nrows, ncols)?;
304 Ok(Self {
305 nrows,
306 ncols,
307 _elem: PhantomData,
308 })
309 }
310
311 pub fn num_elements(&self) -> usize {
313 self.nrows() * self.ncols()
315 }
316
317 fn nrows(&self) -> usize {
319 self.nrows
320 }
321
322 fn ncols(&self) -> usize {
324 self.ncols
325 }
326
327 fn check_slice(&self, slice: &[T]) -> Result<(), SliceError> {
332 let len = self.num_elements();
333
334 if slice.len() != len {
335 Err(SliceError::LengthMismatch {
336 expected: len,
337 found: slice.len(),
338 })
339 } else {
340 Ok(())
341 }
342 }
343
344 unsafe fn box_to_mat(self, b: Box<[T]>) -> Mat<Self> {
350 debug_assert_eq!(b.len(), self.num_elements(), "safety contract violated");
351
352 let ptr = utils::box_into_nonnull(b).cast::<u8>();
353
354 unsafe { Mat::from_raw_parts(self, ptr) }
358 }
359}
360
361#[derive(Debug, Clone, Copy)]
363pub struct Overflow {
364 nrows: usize,
365 ncols: usize,
366 elsize: usize,
367}
368
369impl Overflow {
370 pub(crate) fn for_type<T>(nrows: usize, ncols: usize) -> Self {
372 Self {
373 nrows,
374 ncols,
375 elsize: std::mem::size_of::<T>(),
376 }
377 }
378
379 pub(crate) fn check_byte_budget<T>(
385 capacity: usize,
386 nrows: usize,
387 ncols: usize,
388 ) -> Result<(), Self> {
389 let bytes = std::mem::size_of::<T>().saturating_mul(capacity);
390 if bytes <= isize::MAX as usize {
391 Ok(())
392 } else {
393 Err(Self::for_type::<T>(nrows, ncols))
394 }
395 }
396
397 pub(crate) fn check<T>(nrows: usize, ncols: usize) -> Result<(), Self> {
398 let capacity = nrows
400 .checked_mul(ncols)
401 .ok_or_else(|| Self::for_type::<T>(nrows, ncols))?;
402
403 Self::check_byte_budget::<T>(capacity, nrows, ncols)
404 }
405}
406
407impl std::fmt::Display for Overflow {
408 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
409 if self.elsize == 0 {
410 write!(
411 f,
412 "ZST matrix with dimensions {} x {} has more than `usize::MAX` elements",
413 self.nrows, self.ncols,
414 )
415 } else {
416 write!(
417 f,
418 "a matrix of size {} x {} with element size {} would exceed isize::MAX bytes",
419 self.nrows, self.ncols, self.elsize,
420 )
421 }
422 }
423}
424
425impl std::error::Error for Overflow {}
426
427#[derive(Debug, Clone, Copy, Error)]
429#[non_exhaustive]
430pub enum SliceError {
431 #[error("Length mismatch: expected {expected}, found {found}")]
432 LengthMismatch { expected: usize, found: usize },
433}
434
435unsafe impl<T> Repr for Standard<T> {
439 type Row<'a>
440 = &'a [T]
441 where
442 T: 'a;
443
444 fn nrows(&self) -> usize {
445 self.nrows
446 }
447
448 fn layout(&self) -> Result<Layout, LayoutError> {
449 Ok(Layout::array::<T>(self.num_elements())?)
450 }
451
452 unsafe fn get_row<'a>(self, ptr: NonNull<u8>, i: usize) -> Self::Row<'a> {
453 debug_assert!(ptr.cast::<T>().is_aligned());
454 debug_assert!(i < self.nrows);
455
456 let row_ptr = unsafe { ptr.as_ptr().cast::<T>().add(i * self.ncols) };
460
461 unsafe { std::slice::from_raw_parts(row_ptr, self.ncols) }
463 }
464}
465
466unsafe impl<T> ReprMut for Standard<T> {
469 type RowMut<'a>
470 = &'a mut [T]
471 where
472 T: 'a;
473
474 unsafe fn get_row_mut<'a>(self, ptr: NonNull<u8>, i: usize) -> Self::RowMut<'a> {
475 debug_assert!(ptr.cast::<T>().is_aligned());
476 debug_assert!(i < self.nrows);
477
478 let row_ptr = unsafe { ptr.as_ptr().cast::<T>().add(i * self.ncols) };
482
483 unsafe { std::slice::from_raw_parts_mut(row_ptr, self.ncols) }
486 }
487}
488
489unsafe impl<T> ReprOwned for Standard<T> {
493 unsafe fn drop(self, ptr: NonNull<u8>) {
494 unsafe {
500 let slice_ptr = std::ptr::slice_from_raw_parts_mut(
501 ptr.cast::<T>().as_ptr(),
502 self.nrows * self.ncols,
503 );
504 let _ = Box::from_raw(slice_ptr);
505 }
506 }
507}
508
509unsafe impl<T> NewOwned<T> for Standard<T>
512where
513 T: Clone,
514{
515 type Error = crate::error::Infallible;
516 fn new_owned(self, value: T) -> Result<Mat<Self>, Self::Error> {
517 let b: Box<[T]> = std::iter::repeat_n(value, self.num_elements()).collect();
518
519 Ok(unsafe { self.box_to_mat(b) })
521 }
522}
523
524unsafe impl<T> NewOwned<Defaulted> for Standard<T>
527where
528 T: Default,
529{
530 type Error = crate::error::Infallible;
531 fn new_owned(self, _: Defaulted) -> Result<Mat<Self>, Self::Error> {
532 let b: Box<[T]> = std::iter::repeat_with(T::default)
533 .take(self.num_elements())
534 .collect();
535
536 Ok(unsafe { self.box_to_mat(b) })
538 }
539}
540
541unsafe impl<T> NewRef<T> for Standard<T> {
544 type Error = SliceError;
545 fn new_ref(self, data: &[T]) -> Result<MatRef<'_, Self>, Self::Error> {
546 self.check_slice(data)?;
547
548 Ok(unsafe { MatRef::from_raw_parts(self, utils::as_nonnull(data).cast::<u8>()) })
553 }
554}
555
556unsafe impl<T> NewMut<T> for Standard<T> {
559 type Error = SliceError;
560 fn new_mut(self, data: &mut [T]) -> Result<MatMut<'_, Self>, Self::Error> {
561 self.check_slice(data)?;
562
563 Ok(unsafe { MatMut::from_raw_parts(self, utils::as_nonnull_mut(data).cast::<u8>()) })
568 }
569}
570
571impl<T> NewCloned for Standard<T>
572where
573 T: Clone,
574{
575 fn new_cloned(v: MatRef<'_, Self>) -> Mat<Self> {
576 let b: Box<[T]> = v.as_slice().iter().cloned().collect();
577
578 unsafe { v.repr().box_to_mat(b) }
580 }
581}
582
583#[derive(Debug)]
592pub struct Mat<T: ReprOwned> {
593 ptr: NonNull<u8>,
594 repr: T,
595 _invariant: PhantomData<fn(T) -> T>,
596}
597
598unsafe impl<T> Send for Mat<T> where T: ReprOwned + Send {}
600
601unsafe impl<T> Sync for Mat<T> where T: ReprOwned + Sync {}
603
604impl<T: ReprOwned> Mat<T> {
605 pub fn new<U>(repr: T, init: U) -> Result<Self, <T as NewOwned<U>>::Error>
607 where
608 T: NewOwned<U>,
609 {
610 repr.new_owned(init)
611 }
612
613 #[inline]
615 pub fn num_vectors(&self) -> usize {
616 self.repr.nrows()
617 }
618
619 pub fn repr(&self) -> &T {
621 &self.repr
622 }
623
624 #[must_use]
626 pub fn get_row(&self, i: usize) -> Option<T::Row<'_>> {
627 if i < self.num_vectors() {
628 let row = unsafe { self.get_row_unchecked(i) };
631 Some(row)
632 } else {
633 None
634 }
635 }
636
637 pub(crate) unsafe fn get_row_unchecked(&self, i: usize) -> T::Row<'_> {
638 unsafe { self.repr.get_row(self.ptr, i) }
641 }
642
643 #[must_use]
645 pub fn get_row_mut(&mut self, i: usize) -> Option<T::RowMut<'_>> {
646 if i < self.num_vectors() {
647 Some(unsafe { self.get_row_mut_unchecked(i) })
649 } else {
650 None
651 }
652 }
653
654 pub(crate) unsafe fn get_row_mut_unchecked(&mut self, i: usize) -> T::RowMut<'_> {
655 unsafe { self.repr.get_row_mut(self.ptr, i) }
658 }
659
660 #[inline]
662 pub fn as_view(&self) -> MatRef<'_, T> {
663 MatRef {
664 ptr: self.ptr,
665 repr: self.repr,
666 _lifetime: PhantomData,
667 }
668 }
669
670 #[inline]
672 pub fn as_view_mut(&mut self) -> MatMut<'_, T> {
673 MatMut {
674 ptr: self.ptr,
675 repr: self.repr,
676 _lifetime: PhantomData,
677 }
678 }
679
680 pub fn rows(&self) -> Rows<'_, T> {
682 Rows::new(self.reborrow())
683 }
684
685 pub fn rows_mut(&mut self) -> RowsMut<'_, T> {
687 RowsMut::new(self.reborrow_mut())
688 }
689
690 pub(crate) unsafe fn from_raw_parts(repr: T, ptr: NonNull<u8>) -> Self {
700 Self {
701 ptr,
702 repr,
703 _invariant: PhantomData,
704 }
705 }
706
707 pub fn as_raw_ptr(&self) -> *const u8 {
709 self.ptr.as_ptr()
710 }
711
712 pub(crate) fn as_raw_mut_ptr(&mut self) -> *mut u8 {
714 self.ptr.as_ptr()
715 }
716}
717
718impl<T: ReprOwned> Drop for Mat<T> {
719 fn drop(&mut self) {
720 unsafe { self.repr.drop(self.ptr) };
723 }
724}
725
726impl<T: NewCloned> Clone for Mat<T> {
727 fn clone(&self) -> Self {
728 T::new_cloned(self.as_view())
729 }
730}
731
732impl<T> Mat<Standard<T>> {
733 pub fn from_fn<F: FnMut() -> T>(repr: Standard<T>, mut f: F) -> Self {
735 let b: Box<[T]> = (0..repr.num_elements()).map(|_| f()).collect();
736 unsafe { repr.box_to_mat(b) }
738 }
739
740 #[inline]
742 pub fn vector_dim(&self) -> usize {
743 self.repr.ncols()
744 }
745
746 #[inline]
750 pub fn as_slice(&self) -> &[T] {
751 self.as_view().as_slice()
752 }
753
754 #[inline]
756 pub fn as_matrix_view(&self) -> rowmajor::Ref<'_, T> {
757 self.as_view().as_matrix_view()
758 }
759}
760
761#[derive(Debug, Clone, Copy)]
777pub struct MatRef<'a, T: Repr> {
778 ptr: NonNull<u8>,
779 repr: T,
780 _lifetime: PhantomData<&'a T>,
782}
783
784unsafe impl<T> Send for MatRef<'_, T> where T: Repr + Send {}
786
787unsafe impl<T> Sync for MatRef<'_, T> where T: Repr + Sync {}
789
790impl<'a, T: Repr> MatRef<'a, T> {
791 pub fn new<U>(repr: T, data: &'a [U]) -> Result<Self, T::Error>
793 where
794 T: NewRef<U>,
795 {
796 repr.new_ref(data)
797 }
798
799 #[inline]
801 pub fn num_vectors(&self) -> usize {
802 self.repr.nrows()
803 }
804
805 pub fn repr(&self) -> &T {
807 &self.repr
808 }
809
810 #[must_use]
812 pub fn get_row(&self, i: usize) -> Option<T::Row<'_>> {
813 if i < self.num_vectors() {
814 let row = unsafe { self.get_row_unchecked(i) };
817 Some(row)
818 } else {
819 None
820 }
821 }
822
823 #[inline]
829 pub(crate) unsafe fn get_row_unchecked(&self, i: usize) -> T::Row<'_> {
830 unsafe { self.repr.get_row(self.ptr, i) }
832 }
833
834 pub fn rows(&self) -> Rows<'_, T> {
836 Rows::new(*self)
837 }
838
839 pub fn to_owned(&self) -> Mat<T>
841 where
842 T: NewCloned,
843 {
844 T::new_cloned(*self)
845 }
846
847 pub unsafe fn from_raw_parts(repr: T, ptr: NonNull<u8>) -> Self {
855 Self {
856 ptr,
857 repr,
858 _lifetime: PhantomData,
859 }
860 }
861
862 pub fn as_raw_ptr(&self) -> *const u8 {
864 self.ptr.as_ptr()
865 }
866}
867
868impl<'a, T> MatRef<'a, Standard<T>> {
869 #[inline]
871 pub fn vector_dim(&self) -> usize {
872 self.repr.ncols()
873 }
874
875 #[inline]
879 pub fn as_slice(&self) -> &'a [T] {
880 let len = self.repr.num_elements();
881 unsafe { std::slice::from_raw_parts(self.ptr.as_ptr().cast::<T>(), len) }
884 }
885
886 #[expect(clippy::expect_used)]
888 #[inline]
889 pub fn as_matrix_view(&self) -> rowmajor::Ref<'a, T> {
890 rowmajor::Ref::try_from_data(self.as_slice(), self.num_vectors(), self.vector_dim())
893 .expect("Standard<T> has valid dimensions")
894 }
895}
896
897impl<'this, T: ReprOwned> Reborrow<'this> for Mat<T> {
899 type Target = MatRef<'this, T>;
900
901 fn reborrow(&'this self) -> Self::Target {
902 self.as_view()
903 }
904}
905
906impl<'this, T: ReprOwned> ReborrowMut<'this> for Mat<T> {
908 type Target = MatMut<'this, T>;
909
910 fn reborrow_mut(&'this mut self) -> Self::Target {
911 self.as_view_mut()
912 }
913}
914
915impl<'this, 'a, T: Repr> Reborrow<'this> for MatRef<'a, T> {
917 type Target = MatRef<'this, T>;
918
919 fn reborrow(&'this self) -> Self::Target {
920 MatRef {
921 ptr: self.ptr,
922 repr: self.repr,
923 _lifetime: PhantomData,
924 }
925 }
926}
927
928#[derive(Debug)]
945pub struct MatMut<'a, T: ReprMut> {
946 ptr: NonNull<u8>,
947 repr: T,
948 _lifetime: PhantomData<&'a mut T>,
950}
951
952unsafe impl<T> Send for MatMut<'_, T> where T: ReprMut + Send {}
954
955unsafe impl<T> Sync for MatMut<'_, T> where T: ReprMut + Sync {}
957
958impl<'a, T: ReprMut> MatMut<'a, T> {
959 pub fn new<U>(repr: T, data: &'a mut [U]) -> Result<Self, T::Error>
961 where
962 T: NewMut<U>,
963 {
964 repr.new_mut(data)
965 }
966
967 #[inline]
969 pub fn num_vectors(&self) -> usize {
970 self.repr.nrows()
971 }
972
973 pub fn repr(&self) -> &T {
975 &self.repr
976 }
977
978 #[inline]
980 #[must_use]
981 pub fn get_row(&self, i: usize) -> Option<T::Row<'_>> {
982 if i < self.num_vectors() {
983 Some(unsafe { self.get_row_unchecked(i) })
985 } else {
986 None
987 }
988 }
989
990 #[inline]
996 pub(crate) unsafe fn get_row_unchecked(&self, i: usize) -> T::Row<'_> {
997 unsafe { self.repr.get_row(self.ptr, i) }
999 }
1000
1001 #[inline]
1003 #[must_use]
1004 pub fn get_row_mut(&mut self, i: usize) -> Option<T::RowMut<'_>> {
1005 if i < self.num_vectors() {
1006 Some(unsafe { self.get_row_mut_unchecked(i) })
1008 } else {
1009 None
1010 }
1011 }
1012
1013 #[inline]
1019 pub(crate) unsafe fn get_row_mut_unchecked(&mut self, i: usize) -> T::RowMut<'_> {
1020 unsafe { self.repr.get_row_mut(self.ptr, i) }
1023 }
1024
1025 pub fn as_view(&self) -> MatRef<'_, T> {
1027 MatRef {
1028 ptr: self.ptr,
1029 repr: self.repr,
1030 _lifetime: PhantomData,
1031 }
1032 }
1033
1034 pub fn rows(&self) -> Rows<'_, T> {
1036 Rows::new(self.reborrow())
1037 }
1038
1039 pub fn rows_mut(&mut self) -> RowsMut<'_, T> {
1041 RowsMut::new(self.reborrow_mut())
1042 }
1043
1044 pub fn to_owned(&self) -> Mat<T>
1046 where
1047 T: NewCloned,
1048 {
1049 T::new_cloned(self.as_view())
1050 }
1051
1052 pub unsafe fn from_raw_parts(repr: T, ptr: NonNull<u8>) -> Self {
1059 Self {
1060 ptr,
1061 repr,
1062 _lifetime: PhantomData,
1063 }
1064 }
1065
1066 pub fn as_raw_ptr(&self) -> *const u8 {
1068 self.ptr.as_ptr()
1069 }
1070
1071 pub(crate) fn as_raw_mut_ptr(&mut self) -> *mut u8 {
1073 self.ptr.as_ptr()
1074 }
1075}
1076
1077impl<'this, 'a, T: ReprMut> Reborrow<'this> for MatMut<'a, T> {
1079 type Target = MatRef<'this, T>;
1080
1081 fn reborrow(&'this self) -> Self::Target {
1082 self.as_view()
1083 }
1084}
1085
1086impl<'this, 'a, T: ReprMut> ReborrowMut<'this> for MatMut<'a, T> {
1088 type Target = MatMut<'this, T>;
1089
1090 fn reborrow_mut(&'this mut self) -> Self::Target {
1091 MatMut {
1092 ptr: self.ptr,
1093 repr: self.repr,
1094 _lifetime: PhantomData,
1095 }
1096 }
1097}
1098
1099impl<'a, T> MatMut<'a, Standard<T>> {
1100 #[inline]
1102 pub fn vector_dim(&self) -> usize {
1103 self.repr.ncols()
1104 }
1105
1106 #[inline]
1110 pub fn as_slice(&self) -> &[T] {
1111 self.as_view().as_slice()
1112 }
1113
1114 #[inline]
1116 pub fn as_matrix_view(&self) -> rowmajor::Ref<'_, T> {
1117 self.as_view().as_matrix_view()
1118 }
1119}
1120
1121#[derive(Debug)]
1129pub struct Rows<'a, T: Repr> {
1130 matrix: MatRef<'a, T>,
1131 current: usize,
1132}
1133
1134impl<'a, T> Rows<'a, T>
1135where
1136 T: Repr,
1137{
1138 fn new(matrix: MatRef<'a, T>) -> Self {
1139 Self { matrix, current: 0 }
1140 }
1141}
1142
1143impl<'a, T> Iterator for Rows<'a, T>
1144where
1145 T: Repr + 'a,
1146{
1147 type Item = T::Row<'a>;
1148
1149 fn next(&mut self) -> Option<Self::Item> {
1150 let current = self.current;
1151 if current >= self.matrix.num_vectors() {
1152 None
1153 } else {
1154 self.current += 1;
1155 Some(unsafe { self.matrix.repr.get_row(self.matrix.ptr, current) })
1161 }
1162 }
1163
1164 fn size_hint(&self) -> (usize, Option<usize>) {
1165 let remaining = self.matrix.num_vectors() - self.current;
1166 (remaining, Some(remaining))
1167 }
1168}
1169
1170impl<'a, T> ExactSizeIterator for Rows<'a, T> where T: Repr + 'a {}
1171impl<'a, T> FusedIterator for Rows<'a, T> where T: Repr + 'a {}
1172
1173#[derive(Debug)]
1181pub struct RowsMut<'a, T: ReprMut> {
1182 matrix: MatMut<'a, T>,
1183 current: usize,
1184}
1185
1186impl<'a, T> RowsMut<'a, T>
1187where
1188 T: ReprMut,
1189{
1190 fn new(matrix: MatMut<'a, T>) -> Self {
1191 Self { matrix, current: 0 }
1192 }
1193}
1194
1195impl<'a, T> Iterator for RowsMut<'a, T>
1196where
1197 T: ReprMut + 'a,
1198{
1199 type Item = T::RowMut<'a>;
1200
1201 fn next(&mut self) -> Option<Self::Item> {
1202 let current = self.current;
1203 if current >= self.matrix.num_vectors() {
1204 None
1205 } else {
1206 self.current += 1;
1207 Some(unsafe { self.matrix.repr.get_row_mut(self.matrix.ptr, current) })
1216 }
1217 }
1218
1219 fn size_hint(&self) -> (usize, Option<usize>) {
1220 let remaining = self.matrix.num_vectors() - self.current;
1221 (remaining, Some(remaining))
1222 }
1223}
1224
1225impl<'a, T> ExactSizeIterator for RowsMut<'a, T> where T: ReprMut + 'a {}
1226impl<'a, T> FusedIterator for RowsMut<'a, T> where T: ReprMut + 'a {}
1227
1228#[cfg(test)]
1233mod tests {
1234 use super::*;
1235
1236 use std::fmt::Display;
1237
1238 use diskann_utils::lazy_format;
1239 use diskann_utils::views::rowmajor::Matrix;
1240
1241 fn assert_copy<T: Copy>(_: &T) {}
1243
1244 fn _assert_matref_covariant_lifetime<'long: 'short, 'short, T: Repr>(
1254 v: MatRef<'long, T>,
1255 ) -> MatRef<'short, T> {
1256 v
1257 }
1258
1259 fn _assert_matref_covariant_repr<'long: 'short, 'short, 'a>(
1261 v: MatRef<'a, Standard<&'long u8>>,
1262 ) -> MatRef<'a, Standard<&'short u8>> {
1263 v
1264 }
1265
1266 fn _assert_matmut_covariant_lifetime<'long: 'short, 'short, T: ReprMut>(
1268 v: MatMut<'long, T>,
1269 ) -> MatMut<'short, T> {
1270 v
1271 }
1272
1273 fn edge_cases(nrows: usize) -> Vec<usize> {
1274 let max = usize::MAX;
1275
1276 vec![
1277 nrows,
1278 nrows + 1,
1279 nrows + 11,
1280 nrows + 20,
1281 max / 2,
1282 max.div_ceil(2),
1283 max - 1,
1284 max,
1285 ]
1286 }
1287
1288 fn fill_mat(x: &mut Mat<Standard<usize>>, repr: Standard<usize>) {
1289 assert_eq!(x.repr(), &repr);
1290 assert_eq!(x.num_vectors(), repr.nrows());
1291 assert_eq!(x.vector_dim(), repr.ncols());
1292
1293 for i in 0..x.num_vectors() {
1294 let row = x.get_row_mut(i).unwrap();
1295 assert_eq!(row.len(), repr.ncols());
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_mat_mut(mut x: MatMut<'_, Standard<usize>>, repr: Standard<usize>) {
1307 assert_eq!(x.repr(), &repr);
1308 assert_eq!(x.num_vectors(), repr.nrows());
1309 assert_eq!(x.vector_dim(), repr.ncols());
1310
1311 for i in 0..x.num_vectors() {
1312 let row = x.get_row_mut(i).unwrap();
1313 assert_eq!(row.len(), repr.ncols());
1314
1315 row.iter_mut()
1316 .enumerate()
1317 .for_each(|(j, r)| *r = 10 * i + j);
1318 }
1319
1320 for i in edge_cases(repr.nrows()).into_iter() {
1321 assert!(x.get_row_mut(i).is_none());
1322 }
1323 }
1324
1325 fn fill_rows_mut(x: RowsMut<'_, Standard<usize>>, repr: Standard<usize>) {
1326 assert_eq!(x.len(), repr.nrows());
1327 let mut all_rows: Vec<_> = x.collect();
1329 assert_eq!(all_rows.len(), repr.nrows());
1330 for (i, row) in all_rows.iter_mut().enumerate() {
1331 assert_eq!(row.len(), repr.ncols());
1332 row.iter_mut()
1333 .enumerate()
1334 .for_each(|(j, r)| *r = 10 * i + j);
1335 }
1336 }
1337
1338 fn check_mat(x: &Mat<Standard<usize>>, repr: Standard<usize>, ctx: &dyn Display) {
1339 assert_eq!(x.repr(), &repr);
1340 assert_eq!(x.num_vectors(), repr.nrows());
1341 assert_eq!(x.vector_dim(), repr.ncols());
1342
1343 for i in 0..x.num_vectors() {
1344 let row = x.get_row(i).unwrap();
1345
1346 assert_eq!(row.len(), repr.ncols(), "ctx: {ctx}");
1347 row.iter().enumerate().for_each(|(j, r)| {
1348 assert_eq!(
1349 *r,
1350 10 * i + j,
1351 "mismatched entry at row {}, col {} -- ctx: {}",
1352 i,
1353 j,
1354 ctx
1355 )
1356 });
1357 }
1358
1359 for i in edge_cases(repr.nrows()).into_iter() {
1360 assert!(x.get_row(i).is_none(), "ctx: {ctx}");
1361 }
1362 }
1363
1364 fn check_mat_ref(x: MatRef<'_, Standard<usize>>, repr: Standard<usize>, ctx: &dyn Display) {
1365 assert_eq!(x.repr(), &repr);
1366 assert_eq!(x.num_vectors(), repr.nrows());
1367 assert_eq!(x.vector_dim(), repr.ncols());
1368
1369 assert_copy(&x);
1370 for i in 0..x.num_vectors() {
1371 let row = x.get_row(i).unwrap();
1372 assert_eq!(row.len(), repr.ncols(), "ctx: {ctx}");
1373
1374 row.iter().enumerate().for_each(|(j, r)| {
1375 assert_eq!(
1376 *r,
1377 10 * i + j,
1378 "mismatched entry at row {}, col {} -- ctx: {}",
1379 i,
1380 j,
1381 ctx
1382 )
1383 });
1384 }
1385
1386 for i in edge_cases(repr.nrows()).into_iter() {
1387 assert!(x.get_row(i).is_none(), "ctx: {ctx}");
1388 }
1389 }
1390
1391 fn check_mat_mut(x: MatMut<'_, Standard<usize>>, repr: Standard<usize>, ctx: &dyn Display) {
1392 assert_eq!(x.repr(), &repr);
1393 assert_eq!(x.num_vectors(), repr.nrows());
1394 assert_eq!(x.vector_dim(), repr.ncols());
1395
1396 for i in 0..x.num_vectors() {
1397 let row = x.get_row(i).unwrap();
1398 assert_eq!(row.len(), repr.ncols(), "ctx: {ctx}");
1399
1400 row.iter().enumerate().for_each(|(j, r)| {
1401 assert_eq!(
1402 *r,
1403 10 * i + j,
1404 "mismatched entry at row {}, col {} -- ctx: {}",
1405 i,
1406 j,
1407 ctx
1408 )
1409 });
1410 }
1411
1412 for i in edge_cases(repr.nrows()).into_iter() {
1413 assert!(x.get_row(i).is_none(), "ctx: {ctx}");
1414 }
1415 }
1416
1417 fn check_rows(x: Rows<'_, Standard<usize>>, repr: Standard<usize>, ctx: &dyn Display) {
1418 assert_eq!(x.len(), repr.nrows(), "ctx: {ctx}");
1419 let all_rows: Vec<_> = x.collect();
1420 assert_eq!(all_rows.len(), repr.nrows(), "ctx: {ctx}");
1421 for (i, row) in all_rows.iter().enumerate() {
1422 assert_eq!(row.len(), repr.ncols(), "ctx: {ctx}");
1423 row.iter().enumerate().for_each(|(j, r)| {
1424 assert_eq!(
1425 *r,
1426 10 * i + j,
1427 "mismatched entry at row {}, col {} -- ctx: {}",
1428 i,
1429 j,
1430 ctx
1431 )
1432 });
1433 }
1434 }
1435
1436 #[test]
1441 fn standard_representation() {
1442 let repr = Standard::<f32>::new(4, 3).unwrap();
1443 assert_eq!(repr.nrows(), 4);
1444 assert_eq!(repr.ncols(), 3);
1445
1446 let layout = repr.layout().unwrap();
1447 assert_eq!(layout.size(), 4 * 3 * std::mem::size_of::<f32>());
1448 assert_eq!(layout.align(), std::mem::align_of::<f32>());
1449 }
1450
1451 #[test]
1452 fn standard_zero_dimensions() {
1453 for (nrows, ncols) in [(0, 0), (0, 5), (5, 0)] {
1454 let repr = Standard::<u8>::new(nrows, ncols).unwrap();
1455 assert_eq!(repr.nrows(), nrows);
1456 assert_eq!(repr.ncols(), ncols);
1457 let layout = repr.layout().unwrap();
1458 assert_eq!(layout.size(), 0);
1459 }
1460 }
1461
1462 #[test]
1463 fn standard_check_slice() {
1464 let repr = Standard::<u32>::new(3, 4).unwrap();
1465
1466 let data = vec![0u32; 12];
1468 assert!(repr.check_slice(&data).is_ok());
1469
1470 let short = vec![0u32; 11];
1472 assert!(matches!(
1473 repr.check_slice(&short),
1474 Err(SliceError::LengthMismatch {
1475 expected: 12,
1476 found: 11
1477 })
1478 ));
1479
1480 let long = vec![0u32; 13];
1482 assert!(matches!(
1483 repr.check_slice(&long),
1484 Err(SliceError::LengthMismatch {
1485 expected: 12,
1486 found: 13
1487 })
1488 ));
1489
1490 let overflow_repr = Standard::<u8>::new(usize::MAX, 2).unwrap_err();
1492 assert!(matches!(overflow_repr, Overflow { .. }));
1493 }
1494
1495 #[test]
1496 fn standard_new_rejects_element_count_overflow() {
1497 assert!(Standard::<u8>::new(usize::MAX, 2).is_err());
1499 assert!(Standard::<u8>::new(2, usize::MAX).is_err());
1500 assert!(Standard::<u8>::new(usize::MAX, usize::MAX).is_err());
1501 }
1502
1503 #[test]
1504 fn standard_new_rejects_byte_count_exceeding_isize_max() {
1505 let half = (isize::MAX as usize / std::mem::size_of::<u64>()) + 1;
1507 assert!(Standard::<u64>::new(half, 1).is_err());
1508 assert!(Standard::<u64>::new(1, half).is_err());
1509 }
1510
1511 #[test]
1512 fn standard_new_accepts_boundary_below_isize_max() {
1513 let max_elems = isize::MAX as usize / std::mem::size_of::<u64>();
1515 let repr = Standard::<u64>::new(max_elems, 1).unwrap();
1516 assert_eq!(repr.num_elements(), max_elems);
1517 }
1518
1519 #[test]
1520 fn standard_new_zst_rejects_element_count_overflow() {
1521 assert!(Standard::<()>::new(usize::MAX, 2).is_err());
1524 assert!(Standard::<()>::new(usize::MAX / 2 + 1, 3).is_err());
1525 }
1526
1527 #[test]
1528 fn standard_new_zst_accepts_large_non_overflowing() {
1529 let repr = Standard::<()>::new(usize::MAX, 1).unwrap();
1531 assert_eq!(repr.num_elements(), usize::MAX);
1532 assert_eq!(repr.layout().unwrap().size(), 0);
1533 }
1534
1535 #[test]
1536 fn standard_new_overflow_error_display() {
1537 let err = Standard::<u32>::new(usize::MAX, 2).unwrap_err();
1538 let msg = err.to_string();
1539 assert!(msg.contains("would exceed isize::MAX bytes"), "{msg}");
1540
1541 let zst_err = Standard::<()>::new(usize::MAX, 2).unwrap_err();
1542 let zst_msg = zst_err.to_string();
1543 assert!(zst_msg.contains("ZST matrix"), "{zst_msg}");
1544 assert!(zst_msg.contains("usize::MAX"), "{zst_msg}");
1545 }
1546
1547 #[test]
1552 fn mat_new_and_basic_accessors() {
1553 let mat = Mat::new(Standard::<usize>::new(3, 4).unwrap(), 42usize).unwrap();
1554 let base: *const u8 = mat.as_raw_ptr();
1555
1556 assert_eq!(mat.num_vectors(), 3);
1557 assert_eq!(mat.vector_dim(), 4);
1558
1559 let repr = mat.repr();
1560 assert_eq!(repr.nrows(), 3);
1561 assert_eq!(repr.ncols(), 4);
1562
1563 for (i, r) in mat.rows().enumerate() {
1564 assert_eq!(r, &[42, 42, 42, 42]);
1565 let ptr = r.as_ptr().cast::<u8>();
1566 assert_eq!(
1567 ptr,
1568 base.wrapping_add(std::mem::size_of::<usize>() * mat.repr().ncols() * i),
1569 );
1570 }
1571 }
1572
1573 #[test]
1574 fn mat_new_with_default() {
1575 let mat = Mat::new(Standard::<usize>::new(2, 3).unwrap(), Defaulted).unwrap();
1576 let base: *const u8 = mat.as_raw_ptr();
1577
1578 assert_eq!(mat.num_vectors(), 2);
1579 for (i, row) in mat.rows().enumerate() {
1580 assert!(row.iter().all(|&v| v == 0));
1581
1582 let ptr = row.as_ptr().cast::<u8>();
1583 assert_eq!(
1584 ptr,
1585 base.wrapping_add(std::mem::size_of::<usize>() * mat.repr().ncols() * i),
1586 );
1587 }
1588 }
1589
1590 const ROWS: &[usize] = &[0, 1, 2, 3, 5, 10];
1591 const COLS: &[usize] = &[0, 1, 2, 3, 5, 10];
1592
1593 #[test]
1594 fn test_mat() {
1595 for nrows in ROWS {
1596 for ncols in COLS {
1597 let repr = Standard::<usize>::new(*nrows, *ncols).unwrap();
1598 let ctx = &lazy_format!("nrows = {}, ncols = {}", nrows, ncols);
1599
1600 {
1602 let ctx = &lazy_format!("{ctx} - direct");
1603 let mut mat = Mat::new(repr, Defaulted).unwrap();
1604
1605 assert_eq!(mat.num_vectors(), *nrows);
1606 assert_eq!(mat.vector_dim(), *ncols);
1607
1608 fill_mat(&mut mat, repr);
1609
1610 check_mat(&mat, repr, ctx);
1611 check_mat_ref(mat.reborrow(), repr, ctx);
1612 check_mat_mut(mat.reborrow_mut(), repr, ctx);
1613 check_rows(mat.rows(), repr, ctx);
1614
1615 assert_eq!(mat.as_raw_ptr(), mat.reborrow().as_raw_ptr());
1617 assert_eq!(mat.as_raw_ptr(), mat.reborrow_mut().as_raw_ptr());
1618 }
1619
1620 {
1622 let ctx = &lazy_format!("{ctx} - matmut");
1623 let mut mat = Mat::new(repr, Defaulted).unwrap();
1624 let matmut = mat.reborrow_mut();
1625
1626 assert_eq!(matmut.num_vectors(), *nrows);
1627 assert_eq!(matmut.vector_dim(), *ncols);
1628
1629 fill_mat_mut(matmut, repr);
1630
1631 check_mat(&mat, repr, ctx);
1632 check_mat_ref(mat.reborrow(), repr, ctx);
1633 check_mat_mut(mat.reborrow_mut(), repr, ctx);
1634 check_rows(mat.rows(), repr, ctx);
1635 }
1636
1637 {
1639 let ctx = &lazy_format!("{ctx} - rows_mut");
1640 let mut mat = Mat::new(repr, Defaulted).unwrap();
1641 fill_rows_mut(mat.rows_mut(), repr);
1642
1643 check_mat(&mat, repr, ctx);
1644 check_mat_ref(mat.reborrow(), repr, ctx);
1645 check_mat_mut(mat.reborrow_mut(), repr, ctx);
1646 check_rows(mat.rows(), repr, ctx);
1647 }
1648 }
1649 }
1650 }
1651
1652 #[test]
1653 fn test_mat_clone() {
1654 for nrows in ROWS {
1655 for ncols in COLS {
1656 let repr = Standard::<usize>::new(*nrows, *ncols).unwrap();
1657 let ctx = &lazy_format!("nrows = {}, ncols = {}", nrows, ncols);
1658
1659 let mut mat = Mat::new(repr, Defaulted).unwrap();
1660 fill_mat(&mut mat, repr);
1661
1662 {
1664 let ctx = &lazy_format!("{ctx} - Mat::clone");
1665 let cloned = mat.clone();
1666
1667 assert_eq!(cloned.num_vectors(), *nrows);
1668 assert_eq!(cloned.vector_dim(), *ncols);
1669
1670 check_mat(&cloned, repr, ctx);
1671 check_mat_ref(cloned.reborrow(), repr, ctx);
1672 check_rows(cloned.rows(), repr, ctx);
1673
1674 if repr.num_elements() > 0 {
1676 assert_ne!(mat.as_raw_ptr(), cloned.as_raw_ptr());
1677 }
1678 }
1679
1680 {
1682 let ctx = &lazy_format!("{ctx} - MatRef::to_owned");
1683 let owned = mat.as_view().to_owned();
1684
1685 check_mat(&owned, repr, ctx);
1686 check_mat_ref(owned.reborrow(), repr, ctx);
1687 check_rows(owned.rows(), repr, ctx);
1688
1689 if repr.num_elements() > 0 {
1690 assert_ne!(mat.as_raw_ptr(), owned.as_raw_ptr());
1691 }
1692 }
1693
1694 {
1696 let ctx = &lazy_format!("{ctx} - MatMut::to_owned");
1697 let owned = mat.as_view_mut().to_owned();
1698
1699 check_mat(&owned, repr, ctx);
1700 check_mat_ref(owned.reborrow(), repr, ctx);
1701 check_rows(owned.rows(), repr, ctx);
1702
1703 if repr.num_elements() > 0 {
1704 assert_ne!(mat.as_raw_ptr(), owned.as_raw_ptr());
1705 }
1706 }
1707 }
1708 }
1709 }
1710
1711 #[test]
1712 fn test_mat_refmut() {
1713 for nrows in ROWS {
1714 for ncols in COLS {
1715 let repr = Standard::<usize>::new(*nrows, *ncols).unwrap();
1716 let ctx = &lazy_format!("nrows = {}, ncols = {}", nrows, ncols);
1717
1718 {
1720 let ctx = &lazy_format!("{ctx} - by matmut");
1721 let mut b: Box<[_]> = (0..repr.num_elements()).map(|_| 0usize).collect();
1722 let ptr = b.as_ptr().cast::<u8>();
1723 let mut matmut = MatMut::new(repr, &mut b).unwrap();
1724
1725 assert_eq!(
1726 ptr,
1727 matmut.as_raw_ptr(),
1728 "underlying memory should be preserved",
1729 );
1730
1731 fill_mat_mut(matmut.reborrow_mut(), repr);
1732
1733 check_mat_mut(matmut.reborrow_mut(), repr, ctx);
1734 check_mat_ref(matmut.reborrow(), repr, ctx);
1735 check_rows(matmut.rows(), repr, ctx);
1736 check_rows(matmut.reborrow().rows(), repr, ctx);
1737
1738 let matref = MatRef::new(repr, &b).unwrap();
1739 check_mat_ref(matref, repr, ctx);
1740 check_mat_ref(matref.reborrow(), repr, ctx);
1741 check_rows(matref.rows(), repr, ctx);
1742 }
1743
1744 {
1746 let ctx = &lazy_format!("{ctx} - by rows");
1747 let mut b: Box<[_]> = (0..repr.num_elements()).map(|_| 0usize).collect();
1748 let ptr = b.as_ptr().cast::<u8>();
1749 let mut matmut = MatMut::new(repr, &mut b).unwrap();
1750
1751 assert_eq!(
1752 ptr,
1753 matmut.as_raw_ptr(),
1754 "underlying memory should be preserved",
1755 );
1756
1757 fill_rows_mut(matmut.rows_mut(), repr);
1758
1759 check_mat_mut(matmut.reborrow_mut(), repr, ctx);
1760 check_mat_ref(matmut.reborrow(), repr, ctx);
1761 check_rows(matmut.rows(), repr, ctx);
1762 check_rows(matmut.reborrow().rows(), repr, ctx);
1763
1764 let matref = MatRef::new(repr, &b).unwrap();
1765 check_mat_ref(matref, repr, ctx);
1766 check_mat_ref(matref.reborrow(), repr, ctx);
1767 check_rows(matref.rows(), repr, ctx);
1768 }
1769 }
1770 }
1771 }
1772
1773 #[test]
1778 fn test_standard_new_owned() {
1779 let rows = [0, 1, 2, 3, 5, 10];
1780 let cols = [0, 1, 2, 3, 5, 10];
1781
1782 for nrows in rows {
1783 for ncols in cols {
1784 let m = Mat::new(Standard::new(nrows, ncols).unwrap(), 1usize).unwrap();
1785 let rows_iter = m.rows();
1786 let len = <_ as ExactSizeIterator>::len(&rows_iter);
1787 assert_eq!(len, nrows);
1788 for r in rows_iter {
1789 assert_eq!(r.len(), ncols);
1790 assert!(r.iter().all(|i| *i == 1usize));
1791 }
1792 }
1793 }
1794 }
1795
1796 #[test]
1797 fn test_mat_from_fn() {
1798 let rows = [0, 1, 2, 5];
1799 let cols = [0, 1, 3, 7];
1800
1801 for nrows in rows {
1802 for ncols in cols {
1803 let mut counter = 0u32;
1804 let m = Mat::from_fn(Standard::new(nrows, ncols).unwrap(), || {
1805 let v = counter;
1806 counter += 1;
1807 v
1808 });
1809
1810 assert_eq!(counter as usize, nrows * ncols);
1811 for (i, row) in m.rows().enumerate() {
1812 assert_eq!(row.len(), ncols);
1813 for (j, &v) in row.iter().enumerate() {
1814 assert_eq!(v, (i * ncols + j) as u32);
1815 }
1816 }
1817 }
1818 }
1819 }
1820
1821 #[test]
1822 fn matref_new_slice_length_error() {
1823 let repr = Standard::<u32>::new(3, 4).unwrap();
1824
1825 let data = vec![0u32; 12];
1827 assert!(MatRef::new(repr, &data).is_ok());
1828
1829 let short = vec![0u32; 11];
1831 assert!(matches!(
1832 MatRef::new(repr, &short),
1833 Err(SliceError::LengthMismatch {
1834 expected: 12,
1835 found: 11
1836 })
1837 ));
1838
1839 let long = vec![0u32; 13];
1841 assert!(matches!(
1842 MatRef::new(repr, &long),
1843 Err(SliceError::LengthMismatch {
1844 expected: 12,
1845 found: 13
1846 })
1847 ));
1848 }
1849
1850 #[test]
1851 fn matmut_new_slice_length_error() {
1852 let repr = Standard::<u32>::new(3, 4).unwrap();
1853
1854 let mut data = vec![0u32; 12];
1856 assert!(MatMut::new(repr, &mut data).is_ok());
1857
1858 let mut short = vec![0u32; 11];
1860 assert!(matches!(
1861 MatMut::new(repr, &mut short),
1862 Err(SliceError::LengthMismatch {
1863 expected: 12,
1864 found: 11
1865 })
1866 ));
1867
1868 let mut long = vec![0u32; 13];
1870 assert!(matches!(
1871 MatMut::new(repr, &mut long),
1872 Err(SliceError::LengthMismatch {
1873 expected: 12,
1874 found: 13
1875 })
1876 ));
1877 }
1878
1879 #[test]
1880 fn as_matrix_view_roundtrip() {
1881 let data = [1.0f32, 2.0, 3.0, 4.0, 5.0, 6.0];
1882
1883 let matref = MatRef::new(Standard::new(2, 3).unwrap(), &data).unwrap();
1885 let view = matref.as_matrix_view();
1886 assert_eq!(view.nrows(), 2);
1887 assert_eq!(view.ncols(), 3);
1888 for row in 0..2 {
1889 for col in 0..3 {
1890 assert_eq!(*view.element(row, col), data[row * 3 + col]);
1891 }
1892 }
1893 assert_eq!(matref.as_slice(), &data);
1894
1895 let mut mat = Mat::new(Standard::<f32>::new(2, 3).unwrap(), 0.0f32).unwrap();
1897 for i in 0..2 {
1898 let r = mat.get_row_mut(i).unwrap();
1899 for j in 0..3 {
1900 r[j] = data[i * 3 + j];
1901 }
1902 }
1903 let view = mat.as_matrix_view();
1904 assert_eq!(view.nrows(), 2);
1905 assert_eq!(view.ncols(), 3);
1906 for row in 0..2 {
1907 for col in 0..3 {
1908 assert_eq!(*view.element(row, col), data[row * 3 + col]);
1909 }
1910 }
1911 assert_eq!(mat.as_slice(), &data);
1912
1913 let mut buf = [1.0f32, 2.0, 3.0, 4.0, 5.0, 6.0];
1915 let matmut = MatMut::new(Standard::new(2, 3).unwrap(), &mut buf).unwrap();
1916 let view = matmut.as_matrix_view();
1917 assert_eq!(view.nrows(), 2);
1918 assert_eq!(view.ncols(), 3);
1919 for row in 0..2 {
1920 for col in 0..3 {
1921 assert_eq!(*view.element(row, col), data[row * 3 + col]);
1922 }
1923 }
1924 assert_eq!(matmut.as_slice(), &data);
1925 }
1926
1927 #[test]
1928 fn test_standard_non_copy_element() {
1929 let repr = Standard::<String>::new(2, 3).unwrap();
1930
1931 let filled = Mat::new(repr, String::from("x")).unwrap();
1933 assert_eq!(filled.num_vectors(), 2);
1934 assert!(filled.rows().flatten().all(|s| s == "x"));
1935
1936 let defaulted = Mat::new(repr, Defaulted).unwrap();
1938 assert!(defaulted.rows().flatten().all(String::is_empty));
1939
1940 let mut counter = 0usize;
1942 let mut mat = Mat::from_fn(repr, || {
1943 let s = counter.to_string();
1944 counter += 1;
1945 s
1946 });
1947 assert_eq!(counter, 6);
1948 assert_eq!(mat.get_row(1).unwrap()[0], "3");
1949
1950 mat.get_row_mut(0).unwrap()[0] = String::from("mutated");
1952 assert_eq!(mat.get_row(0).unwrap()[0], "mutated");
1953
1954 let cloned = mat.clone();
1956 assert_ne!(mat.as_raw_ptr(), cloned.as_raw_ptr());
1957 assert_eq!(cloned.get_row(0).unwrap()[0], "mutated");
1958
1959 let data = [String::from("a"), String::from("b")];
1961 let view = MatRef::new(Standard::new(2, 1).unwrap(), &data).unwrap();
1962 assert_eq!(view.get_row(1).unwrap()[0], "b");
1963
1964 let mut data_mut = [String::from("a"), String::from("b")];
1966 let mut view_mut = MatMut::new(Standard::new(1, 2).unwrap(), &mut data_mut).unwrap();
1967 view_mut.get_row_mut(0).unwrap()[1] = String::from("z");
1968 assert_eq!(data_mut[1], "z");
1969 }
1970}