1use super::{Mat, MatMut, MatRef, *};
2use crate::col::ColRef;
3use crate::internal_prelude::*;
4use crate::row::RowRef;
5use crate::utils::bound::{Dim, Partition};
6use crate::{ContiguousFwd, Idx, IdxInc};
7use equator::{assert, debug_assert};
8use faer_traits::Real;
9use generativity::Guard;
10pub struct Ref<
12 'a,
13 T,
14 Rows = usize,
15 Cols = usize,
16 RStride = isize,
17 CStride = isize,
18> {
19 pub(super) imp: MatView<T, Rows, Cols, RStride, CStride>,
20 pub(super) __marker: PhantomData<&'a T>,
21}
22impl<T, Rows: Copy, Cols: Copy, RStride: Copy, CStride: Copy> Copy
23 for Ref<'_, T, Rows, Cols, RStride, CStride>
24{
25}
26impl<T, Rows: Copy, Cols: Copy, RStride: Copy, CStride: Copy> Clone
27 for Ref<'_, T, Rows, Cols, RStride, CStride>
28{
29 #[inline]
30 fn clone(&self) -> Self {
31 *self
32 }
33}
34impl<'short, T, Rows: Copy, Cols: Copy, RStride: Copy, CStride: Copy>
35 Reborrow<'short> for Ref<'_, T, Rows, Cols, RStride, CStride>
36{
37 type Target = Ref<'short, T, Rows, Cols, RStride, CStride>;
38
39 #[inline]
40 fn rb(&'short self) -> Self::Target {
41 *self
42 }
43}
44impl<'short, T, Rows: Copy, Cols: Copy, RStride: Copy, CStride: Copy>
45 ReborrowMut<'short> for Ref<'_, T, Rows, Cols, RStride, CStride>
46{
47 type Target = Ref<'short, T, Rows, Cols, RStride, CStride>;
48
49 #[inline]
50 fn rb_mut(&'short mut self) -> Self::Target {
51 *self
52 }
53}
54impl<'a, T, Rows: Copy, Cols: Copy, RStride: Copy, CStride: Copy> IntoConst
55 for Ref<'a, T, Rows, Cols, RStride, CStride>
56{
57 type Target = Ref<'a, T, Rows, Cols, RStride, CStride>;
58
59 #[inline]
60 fn into_const(self) -> Self::Target {
61 self
62 }
63}
64unsafe impl<T: Sync, Rows: Sync, Cols: Sync, RStride: Sync, CStride: Sync> Sync
65 for Ref<'_, T, Rows, Cols, RStride, CStride>
66{
67}
68unsafe impl<T: Sync, Rows: Send, Cols: Send, RStride: Send, CStride: Send> Send
69 for Ref<'_, T, Rows, Cols, RStride, CStride>
70{
71}
72#[track_caller]
73#[inline]
74fn from_strided_column_major_slice_assert(
75 nrows: usize,
76 ncols: usize,
77 col_stride: usize,
78 len: usize,
79) {
80 if nrows > 0 && ncols > 0 {
81 let last = usize::checked_mul(col_stride, ncols - 1)
82 .and_then(|last_col| last_col.checked_add(nrows - 1));
83 let Some(last) = last else {
84 panic!("address computation of the last matrix element overflowed");
85 };
86 assert!(last < len);
87 }
88}
89impl<'a, T> MatRef<'a, T> {
90 #[inline]
93 pub fn from_row_major_array<const ROWS: usize, const COLS: usize>(
94 array: &'a [[T; COLS]; ROWS],
95 ) -> Self {
96 unsafe {
97 Self::from_raw_parts(
98 array as *const _ as *const T,
99 ROWS,
100 COLS,
101 COLS as isize,
102 1,
103 )
104 }
105 }
106
107 #[inline]
110 pub fn from_column_major_array<const ROWS: usize, const COLS: usize>(
111 array: &'a [[T; ROWS]; COLS],
112 ) -> Self {
113 unsafe {
114 Self::from_raw_parts(
115 array as *const _ as *const T,
116 ROWS,
117 COLS,
118 1,
119 ROWS as isize,
120 )
121 }
122 }
123
124 #[inline]
126 pub fn from_ref(value: &'a T) -> Self {
127 unsafe { MatRef::from_raw_parts(value as *const T, 1, 1, 0, 0) }
128 }
129}
130
131impl<'a, T, Rows: Shape> ColRef<'a, T, Rows> {
132 #[inline]
135 pub fn from_repeated_ref(value: &'a T, nrows: Rows) -> Self {
136 unsafe { ColRef::from_raw_parts(value as *const T, nrows, 0) }
137 }
138}
139
140impl<'a, T, Cols: Shape> RowRef<'a, T, Cols> {
141 #[inline]
144 pub fn from_repeated_ref(value: &'a T, ncols: Cols) -> Self {
145 unsafe { RowRef::from_raw_parts(value as *const T, ncols, 0) }
146 }
147}
148
149impl<'a, T, Rows: Shape, Cols: Shape> MatRef<'a, T, Rows, Cols> {
150 #[inline]
153 pub fn from_repeated_ref(value: &'a T, nrows: Rows, ncols: Cols) -> Self {
154 unsafe { MatRef::from_raw_parts(value as *const T, nrows, ncols, 0, 0) }
155 }
156
157 #[inline]
160 pub fn from_repeated_col(col: ColRef<'a, T, Rows>, ncols: Cols) -> Self {
161 unsafe {
162 MatRef::from_raw_parts(
163 col.as_ptr(),
164 col.nrows(),
165 ncols,
166 col.row_stride(),
167 0,
168 )
169 }
170 }
171
172 #[inline]
175 pub fn from_repeated_row(row: RowRef<'a, T, Cols>, nrows: Rows) -> Self {
176 unsafe {
177 MatRef::from_raw_parts(
178 row.as_ptr(),
179 nrows,
180 row.ncols(),
181 0,
182 row.col_stride(),
183 )
184 }
185 }
186
187 #[inline]
206 #[track_caller]
207 pub fn from_column_major_slice(
208 slice: &'a [T],
209 nrows: Rows,
210 ncols: Cols,
211 ) -> Self {
212 from_slice_assert(nrows.unbound(), ncols.unbound(), slice.len());
213 unsafe {
214 MatRef::from_raw_parts(
215 slice.as_ptr(),
216 nrows,
217 ncols,
218 1,
219 nrows.unbound() as isize,
220 )
221 }
222 }
223
224 #[inline]
229 #[track_caller]
230 pub fn from_column_major_slice_with_stride(
231 slice: &'a [T],
232 nrows: Rows,
233 ncols: Cols,
234 col_stride: usize,
235 ) -> Self {
236 from_strided_column_major_slice_assert(
237 nrows.unbound(),
238 ncols.unbound(),
239 col_stride,
240 slice.len(),
241 );
242 unsafe {
243 MatRef::from_raw_parts(
244 slice.as_ptr(),
245 nrows,
246 ncols,
247 1,
248 col_stride as isize,
249 )
250 }
251 }
252
253 #[inline]
272 #[track_caller]
273 pub fn from_row_major_slice(
274 slice: &'a [T],
275 nrows: Rows,
276 ncols: Cols,
277 ) -> Self {
278 MatRef::from_column_major_slice(slice, ncols, nrows).transpose()
279 }
280
281 #[inline]
286 #[track_caller]
287 pub fn from_row_major_slice_with_stride(
288 slice: &'a [T],
289 nrows: Rows,
290 ncols: Cols,
291 row_stride: usize,
292 ) -> Self {
293 MatRef::from_column_major_slice_with_stride(
294 slice, ncols, nrows, row_stride,
295 )
296 .transpose()
297 }
298}
299impl<'a, T, Rows: Shape, Cols: Shape, RStride: Stride, CStride: Stride>
300 MatRef<'a, T, Rows, Cols, RStride, CStride>
301{
302 #[inline]
344 #[track_caller]
345 pub const unsafe fn from_raw_parts(
346 ptr: *const T,
347 nrows: Rows,
348 ncols: Cols,
349 row_stride: RStride,
350 col_stride: CStride,
351 ) -> Self {
352 Self(Ref {
353 imp: MatView {
354 ptr: NonNull::new_unchecked(ptr as *mut T),
355 nrows,
356 ncols,
357 row_stride,
358 col_stride,
359 },
360 __marker: PhantomData,
361 })
362 }
363
364 #[inline]
366 pub fn as_ptr(&self) -> *const T {
367 self.imp.ptr.as_ptr() as *const T
368 }
369
370 #[inline]
372 pub fn nrows(&self) -> Rows {
373 self.imp.nrows
374 }
375
376 #[inline]
378 pub fn ncols(&self) -> Cols {
379 self.imp.ncols
380 }
381
382 #[inline]
384 pub fn shape(&self) -> (Rows, Cols) {
385 (self.nrows(), self.ncols())
386 }
387
388 #[inline]
391 pub fn row_stride(&self) -> RStride {
392 self.imp.row_stride
393 }
394
395 #[inline]
398 pub fn col_stride(&self) -> CStride {
399 self.imp.col_stride
400 }
401
402 #[inline]
403 pub fn map<U>(&self, f: impl FnMut(&T) -> U) -> Mat<U, Rows, Cols> {
404 let mut f = f;
405 zip!(self).map(|unzip!(x)| f(x))
406 }
407
408 #[inline]
409 pub fn for_each(&self, f: impl FnMut(&T)) {
410 let mut f = f;
411 zip!(self).for_each(|unzip!(x)| f(x))
412 }
413
414 #[inline]
416 pub fn ptr_at(&self, row: IdxInc<Rows>, col: IdxInc<Cols>) -> *const T {
417 let ptr = self.as_ptr();
418 if row >= self.nrows() || col >= self.ncols() {
419 ptr
420 } else {
421 ptr.wrapping_offset(
422 row.unbound() as isize * self.row_stride().element_stride(),
423 )
424 .wrapping_offset(
425 col.unbound() as isize * self.col_stride().element_stride(),
426 )
427 }
428 }
429
430 #[inline]
439 #[track_caller]
440 pub unsafe fn ptr_inbounds_at(
441 &self,
442 row: Idx<Rows>,
443 col: Idx<Cols>,
444 ) -> *const T {
445 debug_assert!(all(row < self.nrows(), col < self.ncols()));
446 self.as_ptr()
447 .offset(row.unbound() as isize * self.row_stride().element_stride())
448 .offset(col.unbound() as isize * self.col_stride().element_stride())
449 }
450
451 #[inline]
464 #[track_caller]
465 pub fn split_at(
466 self,
467 row: IdxInc<Rows>,
468 col: IdxInc<Cols>,
469 ) -> (
470 MatRef<'a, T, usize, usize, RStride, CStride>,
471 MatRef<'a, T, usize, usize, RStride, CStride>,
472 MatRef<'a, T, usize, usize, RStride, CStride>,
473 MatRef<'a, T, usize, usize, RStride, CStride>,
474 ) {
475 assert!(all(row <= self.nrows(), col <= self.ncols()));
476 let rs = self.row_stride();
477 let cs = self.col_stride();
478 let top_left = self.ptr_at(Rows::start(), Cols::start());
479 let top_right = self.ptr_at(Rows::start(), col);
480 let bot_left = self.ptr_at(row, Cols::start());
481 let bot_right = self.ptr_at(row, col);
482 unsafe {
483 (
484 MatRef::from_raw_parts(
485 top_left,
486 row.unbound(),
487 col.unbound(),
488 rs,
489 cs,
490 ),
491 MatRef::from_raw_parts(
492 top_right,
493 row.unbound(),
494 self.ncols().unbound() - col.unbound(),
495 rs,
496 cs,
497 ),
498 MatRef::from_raw_parts(
499 bot_left,
500 self.nrows().unbound() - row.unbound(),
501 col.unbound(),
502 rs,
503 cs,
504 ),
505 MatRef::from_raw_parts(
506 bot_right,
507 self.nrows().unbound() - row.unbound(),
508 self.ncols().unbound() - col.unbound(),
509 rs,
510 cs,
511 ),
512 )
513 }
514 }
515
516 #[inline]
525 #[track_caller]
526 pub fn split_at_row(
527 self,
528 row: IdxInc<Rows>,
529 ) -> (
530 MatRef<'a, T, usize, Cols, RStride, CStride>,
531 MatRef<'a, T, usize, Cols, RStride, CStride>,
532 ) {
533 assert!(all(row <= self.nrows()));
534 let rs = self.row_stride();
535 let cs = self.col_stride();
536 let top = self.ptr_at(Rows::start(), Cols::start());
537 let bot = self.ptr_at(row, Cols::start());
538 unsafe {
539 (
540 MatRef::from_raw_parts(
541 top,
542 row.unbound(),
543 self.ncols(),
544 rs,
545 cs,
546 ),
547 MatRef::from_raw_parts(
548 bot,
549 self.nrows().unbound() - row.unbound(),
550 self.ncols(),
551 rs,
552 cs,
553 ),
554 )
555 }
556 }
557
558 #[inline]
567 #[track_caller]
568 pub fn split_at_col(
569 self,
570 col: IdxInc<Cols>,
571 ) -> (
572 MatRef<'a, T, Rows, usize, RStride, CStride>,
573 MatRef<'a, T, Rows, usize, RStride, CStride>,
574 ) {
575 assert!(all(col <= self.ncols()));
576 let rs = self.row_stride();
577 let cs = self.col_stride();
578 let left = self.ptr_at(Rows::start(), Cols::start());
579 let right = self.ptr_at(Rows::start(), col);
580 unsafe {
581 (
582 MatRef::from_raw_parts(
583 left,
584 self.nrows(),
585 col.unbound(),
586 rs,
587 cs,
588 ),
589 MatRef::from_raw_parts(
590 right,
591 self.nrows(),
592 self.ncols().unbound() - col.unbound(),
593 rs,
594 cs,
595 ),
596 )
597 }
598 }
599
600 #[inline]
612 pub fn transpose(self) -> MatRef<'a, T, Cols, Rows, CStride, RStride> {
613 MatRef {
614 0: Ref {
615 imp: MatView {
616 ptr: self.imp.ptr,
617 nrows: self.imp.ncols,
618 ncols: self.imp.nrows,
619 row_stride: self.imp.col_stride,
620 col_stride: self.imp.row_stride,
621 },
622 __marker: PhantomData,
623 },
624 }
625 }
626
627 #[inline]
629 pub fn conjugate(self) -> MatRef<'a, T::Conj, Rows, Cols, RStride, CStride>
630 where
631 T: Conjugate,
632 {
633 unsafe {
634 MatRef::from_raw_parts(
635 self.as_ptr() as *const T::Conj,
636 self.nrows(),
637 self.ncols(),
638 self.row_stride(),
639 self.col_stride(),
640 )
641 }
642 }
643
644 #[inline]
646 pub fn canonical(
647 self,
648 ) -> MatRef<'a, T::Canonical, Rows, Cols, RStride, CStride>
649 where
650 T: Conjugate,
651 {
652 unsafe {
653 MatRef::from_raw_parts(
654 self.as_ptr() as *const T::Canonical,
655 self.nrows(),
656 self.ncols(),
657 self.row_stride(),
658 self.col_stride(),
659 )
660 }
661 }
662
663 #[inline]
664 #[doc(hidden)]
665 pub fn __canonicalize(
666 self,
667 ) -> (MatRef<'a, T::Canonical, Rows, Cols, RStride, CStride>, Conj)
668 where
669 T: Conjugate,
670 {
671 (self.canonical(), Conj::get::<T>())
672 }
673
674 #[inline]
676 pub fn adjoint(self) -> MatRef<'a, T::Conj, Cols, Rows, CStride, RStride>
677 where
678 T: Conjugate,
679 {
680 self.conjugate().transpose()
681 }
682
683 #[inline]
684 #[track_caller]
685 pub(crate) fn at(self, row: Idx<Rows>, col: Idx<Cols>) -> &'a T {
686 assert!(all(row < self.nrows(), col < self.ncols()));
687 unsafe { self.at_unchecked(row, col) }
688 }
689
690 #[inline]
691 #[track_caller]
692 pub(crate) unsafe fn at_unchecked(
693 self,
694 row: Idx<Rows>,
695 col: Idx<Cols>,
696 ) -> &'a T {
697 &*self.ptr_inbounds_at(row, col)
698 }
699
700 #[inline]
712 pub fn reverse_rows(
713 self,
714 ) -> MatRef<'a, T, Rows, Cols, RStride::Rev, CStride> {
715 let row = unsafe {
716 IdxInc::<Rows>::new_unbound(
717 self.nrows().unbound().saturating_sub(1),
718 )
719 };
720 let ptr = self.ptr_at(row, Cols::start());
721 unsafe {
722 MatRef::from_raw_parts(
723 ptr,
724 self.nrows(),
725 self.ncols(),
726 self.row_stride().rev(),
727 self.col_stride(),
728 )
729 }
730 }
731
732 #[inline]
744 pub fn reverse_cols(
745 self,
746 ) -> MatRef<'a, T, Rows, Cols, RStride, CStride::Rev> {
747 let col = unsafe {
748 IdxInc::<Cols>::new_unbound(
749 self.ncols().unbound().saturating_sub(1),
750 )
751 };
752 let ptr = self.ptr_at(Rows::start(), col);
753 unsafe {
754 MatRef::from_raw_parts(
755 ptr,
756 self.nrows(),
757 self.ncols(),
758 self.row_stride(),
759 self.col_stride().rev(),
760 )
761 }
762 }
763
764 #[inline]
777 pub fn reverse_rows_and_cols(
778 self,
779 ) -> MatRef<'a, T, Rows, Cols, RStride::Rev, CStride::Rev> {
780 self.reverse_rows().reverse_cols()
781 }
782
783 #[inline]
811 #[track_caller]
812 pub fn submatrix<V: Shape, H: Shape>(
813 self,
814 row_start: IdxInc<Rows>,
815 col_start: IdxInc<Cols>,
816 nrows: V,
817 ncols: H,
818 ) -> MatRef<'a, T, V, H, RStride, CStride> {
819 assert!(all(row_start <= self.nrows(), col_start <= self.ncols()));
820 {
821 let nrows = nrows.unbound();
822 let full_nrows = self.nrows().unbound();
823 let row_start = row_start.unbound();
824 let ncols = ncols.unbound();
825 let full_ncols = self.ncols().unbound();
826 let col_start = col_start.unbound();
827 assert!(all(
828 nrows <= full_nrows - row_start,
829 ncols <= full_ncols - col_start,
830 ));
831 }
832 let rs = self.row_stride();
833 let cs = self.col_stride();
834 unsafe {
835 MatRef::from_raw_parts(
836 self.ptr_at(row_start, col_start),
837 nrows,
838 ncols,
839 rs,
840 cs,
841 )
842 }
843 }
844
845 #[inline]
868 #[track_caller]
869 pub fn subrows<V: Shape>(
870 self,
871 row_start: IdxInc<Rows>,
872 nrows: V,
873 ) -> MatRef<'a, T, V, Cols, RStride, CStride> {
874 assert!(all(row_start <= self.nrows()));
875 {
876 let nrows = nrows.unbound();
877 let full_nrows = self.nrows().unbound();
878 let row_start = row_start.unbound();
879 assert!(all(nrows <= full_nrows - row_start));
880 }
881 let rs = self.row_stride();
882 let cs = self.col_stride();
883 unsafe {
884 MatRef::from_raw_parts(
885 self.ptr_at(row_start, Cols::start()),
886 nrows,
887 self.ncols(),
888 rs,
889 cs,
890 )
891 }
892 }
893
894 #[inline]
917 #[track_caller]
918 pub fn subcols<H: Shape>(
919 self,
920 col_start: IdxInc<Cols>,
921 ncols: H,
922 ) -> MatRef<'a, T, Rows, H, RStride, CStride> {
923 assert!(all(col_start <= self.ncols()));
924 {
925 let ncols = ncols.unbound();
926 let full_ncols = self.ncols().unbound();
927 let col_start = col_start.unbound();
928 assert!(all(ncols <= full_ncols - col_start));
929 }
930 let rs = self.row_stride();
931 let cs = self.col_stride();
932 unsafe {
933 MatRef::from_raw_parts(
934 self.ptr_at(Rows::start(), col_start),
935 self.nrows(),
936 ncols,
937 rs,
938 cs,
939 )
940 }
941 }
942
943 #[inline]
946 #[track_caller]
947 pub fn as_shape<V: Shape, H: Shape>(
948 self,
949 nrows: V,
950 ncols: H,
951 ) -> MatRef<'a, T, V, H, RStride, CStride> {
952 assert!(all(
953 self.nrows().unbound() == nrows.unbound(),
954 self.ncols().unbound() == ncols.unbound(),
955 ));
956 unsafe {
957 MatRef::from_raw_parts(
958 self.as_ptr(),
959 nrows,
960 ncols,
961 self.row_stride(),
962 self.col_stride(),
963 )
964 }
965 }
966
967 #[inline]
970 #[track_caller]
971 pub fn as_row_shape<V: Shape>(
972 self,
973 nrows: V,
974 ) -> MatRef<'a, T, V, Cols, RStride, CStride> {
975 assert!(all(self.nrows().unbound() == nrows.unbound()));
976 unsafe {
977 MatRef::from_raw_parts(
978 self.as_ptr(),
979 nrows,
980 self.ncols(),
981 self.row_stride(),
982 self.col_stride(),
983 )
984 }
985 }
986
987 #[inline]
990 #[track_caller]
991 pub fn as_col_shape<H: Shape>(
992 self,
993 ncols: H,
994 ) -> MatRef<'a, T, Rows, H, RStride, CStride> {
995 assert!(all(self.ncols().unbound() == ncols.unbound()));
996 unsafe {
997 MatRef::from_raw_parts(
998 self.as_ptr(),
999 self.nrows(),
1000 ncols,
1001 self.row_stride(),
1002 self.col_stride(),
1003 )
1004 }
1005 }
1006
1007 #[inline]
1009 pub fn as_dyn_stride(self) -> MatRef<'a, T, Rows, Cols, isize, isize> {
1010 unsafe {
1011 MatRef::from_raw_parts(
1012 self.as_ptr(),
1013 self.nrows(),
1014 self.ncols(),
1015 self.row_stride().element_stride(),
1016 self.col_stride().element_stride(),
1017 )
1018 }
1019 }
1020
1021 #[inline]
1023 pub fn as_dyn(self) -> MatRef<'a, T, usize, usize, RStride, CStride> {
1024 unsafe {
1025 MatRef::from_raw_parts(
1026 self.as_ptr(),
1027 self.nrows().unbound(),
1028 self.ncols().unbound(),
1029 self.row_stride(),
1030 self.col_stride(),
1031 )
1032 }
1033 }
1034
1035 #[inline]
1037 pub fn as_dyn_rows(self) -> MatRef<'a, T, usize, Cols, RStride, CStride> {
1038 unsafe {
1039 MatRef::from_raw_parts(
1040 self.as_ptr(),
1041 self.nrows().unbound(),
1042 self.ncols(),
1043 self.row_stride(),
1044 self.col_stride(),
1045 )
1046 }
1047 }
1048
1049 #[inline]
1051 pub fn as_dyn_cols(self) -> MatRef<'a, T, Rows, usize, RStride, CStride> {
1052 unsafe {
1053 MatRef::from_raw_parts(
1054 self.as_ptr(),
1055 self.nrows(),
1056 self.ncols().unbound(),
1057 self.row_stride(),
1058 self.col_stride(),
1059 )
1060 }
1061 }
1062
1063 #[inline]
1069 #[track_caller]
1070 pub fn row(self, i: Idx<Rows>) -> RowRef<'a, T, Cols, CStride> {
1071 assert!(i < self.nrows());
1072 unsafe {
1073 RowRef::from_raw_parts(
1074 self.ptr_at(i.into(), Cols::start()),
1075 self.ncols(),
1076 self.col_stride(),
1077 )
1078 }
1079 }
1080
1081 #[inline]
1087 #[track_caller]
1088 pub fn col(self, j: Idx<Cols>) -> ColRef<'a, T, Rows, RStride> {
1089 assert!(j < self.ncols());
1090 unsafe {
1091 ColRef::from_raw_parts(
1092 self.ptr_at(Rows::start(), j.into()),
1093 self.nrows(),
1094 self.row_stride(),
1095 )
1096 }
1097 }
1098
1099 #[inline]
1101 pub fn col_iter(
1102 self,
1103 ) -> impl 'a
1104 + ExactSizeIterator
1105 + DoubleEndedIterator<Item = ColRef<'a, T, Rows, RStride>>
1106 where
1107 Rows: 'a,
1108 Cols: 'a,
1109 {
1110 Cols::indices(Cols::start(), self.ncols().end())
1111 .map(move |j| self.col(j))
1112 }
1113
1114 #[inline]
1116 pub fn row_iter(
1117 self,
1118 ) -> impl 'a
1119 + ExactSizeIterator
1120 + DoubleEndedIterator<Item = RowRef<'a, T, Cols, CStride>>
1121 where
1122 Rows: 'a,
1123 Cols: 'a,
1124 {
1125 Rows::indices(Rows::start(), self.nrows().end())
1126 .map(move |i| self.row(i))
1127 }
1128
1129 #[inline]
1131 #[cfg(feature = "rayon")]
1132 pub fn par_col_iter(
1133 self,
1134 ) -> impl 'a
1135 + rayon::iter::IndexedParallelIterator<
1136 Item = ColRef<'a, T, Rows, RStride>,
1137 >
1138 where
1139 T: Sync,
1140 Rows: 'a,
1141 Cols: 'a,
1142 {
1143 use rayon::prelude::*;
1144 #[inline]
1145 fn col_fn<T, Rows: Shape, RStride: Stride, CStride: Stride>(
1146 col: MatRef<'_, T, Rows, usize, RStride, CStride>,
1147 ) -> ColRef<'_, T, Rows, RStride> {
1148 col.col(0)
1149 }
1150 self.par_col_chunks(1).map(col_fn)
1151 }
1152
1153 #[inline]
1155 #[cfg(feature = "rayon")]
1156 pub fn par_row_iter(
1157 self,
1158 ) -> impl 'a
1159 + rayon::iter::IndexedParallelIterator<
1160 Item = RowRef<'a, T, Cols, CStride>,
1161 >
1162 where
1163 T: Sync,
1164 Rows: 'a,
1165 Cols: 'a,
1166 {
1167 use rayon::prelude::*;
1168 self.transpose().par_col_iter().map(ColRef::transpose)
1169 }
1170
1171 #[inline]
1179 #[track_caller]
1180 #[cfg(feature = "rayon")]
1181 pub fn par_col_chunks(
1182 self,
1183 chunk_size: usize,
1184 ) -> impl 'a
1185 + rayon::iter::IndexedParallelIterator<
1186 Item = MatRef<'a, T, Rows, usize, RStride, CStride>,
1187 >
1188 where
1189 T: Sync,
1190 Rows: 'a,
1191 Cols: 'a,
1192 {
1193 use rayon::prelude::*;
1194 let this = self.as_dyn_cols();
1195 assert!(chunk_size > 0);
1196 let chunk_count = this.ncols().msrv_div_ceil(chunk_size);
1197 (0..chunk_count).into_par_iter().map(move |chunk_idx| {
1198 let pos = chunk_size * chunk_idx;
1199 this.subcols(pos, Ord::min(chunk_size, this.ncols() - pos))
1200 })
1201 }
1202
1203 #[inline]
1208 #[track_caller]
1209 #[cfg(feature = "rayon")]
1210 pub fn par_col_partition(
1211 self,
1212 count: usize,
1213 ) -> impl 'a
1214 + rayon::iter::IndexedParallelIterator<
1215 Item = MatRef<'a, T, Rows, usize, RStride, CStride>,
1216 >
1217 where
1218 T: Sync,
1219 Rows: 'a,
1220 Cols: 'a,
1221 {
1222 use rayon::prelude::*;
1223 let this = self.as_dyn_cols();
1224 assert!(count > 0);
1225 (0..count).into_par_iter().map(move |chunk_idx| {
1226 let (start, len) = crate::utils::thread::par_split_indices(
1227 this.ncols(),
1228 chunk_idx,
1229 count,
1230 );
1231 this.subcols(start, len)
1232 })
1233 }
1234
1235 #[inline]
1243 #[track_caller]
1244 #[cfg(feature = "rayon")]
1245 pub fn par_row_chunks(
1246 self,
1247 chunk_size: usize,
1248 ) -> impl 'a
1249 + rayon::iter::IndexedParallelIterator<
1250 Item = MatRef<'a, T, usize, Cols, RStride, CStride>,
1251 >
1252 where
1253 T: Sync,
1254 Rows: 'a,
1255 Cols: 'a,
1256 {
1257 use rayon::prelude::*;
1258 self.transpose()
1259 .par_col_chunks(chunk_size)
1260 .map(MatRef::transpose)
1261 }
1262
1263 #[inline]
1268 #[track_caller]
1269 #[cfg(feature = "rayon")]
1270 pub fn par_row_partition(
1271 self,
1272 count: usize,
1273 ) -> impl 'a
1274 + rayon::iter::IndexedParallelIterator<
1275 Item = MatRef<'a, T, usize, Cols, RStride, CStride>,
1276 >
1277 where
1278 T: Sync,
1279 Rows: 'a,
1280 Cols: 'a,
1281 {
1282 use rayon::prelude::*;
1283 self.transpose()
1284 .par_col_partition(count)
1285 .map(MatRef::transpose)
1286 }
1287
1288 #[inline]
1291 pub fn split_first_row(
1292 self,
1293 ) -> Option<(
1294 RowRef<'a, T, Cols, CStride>,
1295 MatRef<'a, T, usize, Cols, RStride, CStride>,
1296 )> {
1297 if let Some(i0) = self.nrows().idx_inc(1) {
1298 let (head, tail) = self.split_at_row(i0);
1299 Some((head.row(0), tail))
1300 } else {
1301 None
1302 }
1303 }
1304
1305 #[inline]
1308 pub fn split_first_col(
1309 self,
1310 ) -> Option<(
1311 ColRef<'a, T, Rows, RStride>,
1312 MatRef<'a, T, Rows, usize, RStride, CStride>,
1313 )> {
1314 if let Some(i0) = self.ncols().idx_inc(1) {
1315 let (head, tail) = self.split_at_col(i0);
1316 Some((head.col(0), tail))
1317 } else {
1318 None
1319 }
1320 }
1321
1322 #[inline]
1325 pub fn split_last_row(
1326 self,
1327 ) -> Option<(
1328 RowRef<'a, T, Cols, CStride>,
1329 MatRef<'a, T, usize, Cols, RStride, CStride>,
1330 )> {
1331 if self.nrows().unbound() > 0 {
1332 let i0 = self.nrows().checked_idx_inc(self.nrows().unbound() - 1);
1333 let (head, tail) = self.split_at_row(i0);
1334 Some((tail.row(0), head))
1335 } else {
1336 None
1337 }
1338 }
1339
1340 #[inline]
1343 pub fn split_last_col(
1344 self,
1345 ) -> Option<(
1346 ColRef<'a, T, Rows, RStride>,
1347 MatRef<'a, T, Rows, usize, RStride, CStride>,
1348 )> {
1349 if self.ncols().unbound() > 0 {
1350 let i0 = self.ncols().checked_idx_inc(self.ncols().unbound() - 1);
1351 let (head, tail) = self.split_at_col(i0);
1352 Some((tail.col(0), head))
1353 } else {
1354 None
1355 }
1356 }
1357
1358 #[inline]
1361 pub fn try_as_row_major(
1362 self,
1363 ) -> Option<MatRef<'a, T, Rows, Cols, RStride, ContiguousFwd>> {
1364 if self.col_stride().element_stride() == 1 {
1365 Some(unsafe {
1366 MatRef::from_raw_parts(
1367 self.as_ptr(),
1368 self.nrows(),
1369 self.ncols(),
1370 self.row_stride(),
1371 ContiguousFwd,
1372 )
1373 })
1374 } else {
1375 None
1376 }
1377 }
1378
1379 #[doc(hidden)]
1380 #[inline]
1381 pub fn bind<'M, 'N>(
1382 self,
1383 row: Guard<'M>,
1384 col: Guard<'N>,
1385 ) -> MatRef<'a, T, Dim<'M>, Dim<'N>, RStride, CStride> {
1386 unsafe {
1387 MatRef::from_raw_parts(
1388 self.as_ptr(),
1389 self.nrows().bind(row),
1390 self.ncols().bind(col),
1391 self.row_stride(),
1392 self.col_stride(),
1393 )
1394 }
1395 }
1396
1397 #[doc(hidden)]
1398 #[inline]
1399 pub fn bind_r<'M>(
1400 self,
1401 row: Guard<'M>,
1402 ) -> MatRef<'a, T, Dim<'M>, Cols, RStride, CStride> {
1403 unsafe {
1404 MatRef::from_raw_parts(
1405 self.as_ptr(),
1406 self.nrows().bind(row),
1407 self.ncols(),
1408 self.row_stride(),
1409 self.col_stride(),
1410 )
1411 }
1412 }
1413
1414 #[doc(hidden)]
1415 #[inline]
1416 pub fn bind_c<'N>(
1417 self,
1418 col: Guard<'N>,
1419 ) -> MatRef<'a, T, Rows, Dim<'N>, RStride, CStride> {
1420 unsafe {
1421 MatRef::from_raw_parts(
1422 self.as_ptr(),
1423 self.nrows(),
1424 self.ncols().bind(col),
1425 self.row_stride(),
1426 self.col_stride(),
1427 )
1428 }
1429 }
1430
1431 #[doc(hidden)]
1432 #[inline]
1433 pub unsafe fn const_cast(
1434 self,
1435 ) -> MatMut<'a, T, Rows, Cols, RStride, CStride> {
1436 MatMut::from_raw_parts_mut(
1437 self.as_ptr() as *mut T,
1438 self.nrows(),
1439 self.ncols(),
1440 self.row_stride(),
1441 self.col_stride(),
1442 )
1443 }
1444
1445 #[inline]
1448 pub fn try_as_col_major(
1449 self,
1450 ) -> Option<MatRef<'a, T, Rows, Cols, ContiguousFwd, CStride>> {
1451 if self.row_stride().element_stride() == 1 {
1452 Some(unsafe {
1453 MatRef::from_raw_parts(
1454 self.as_ptr(),
1455 self.nrows(),
1456 self.ncols(),
1457 ContiguousFwd,
1458 self.col_stride(),
1459 )
1460 })
1461 } else {
1462 None
1463 }
1464 }
1465
1466 #[track_caller]
1474 #[inline]
1475 pub fn get<RowRange, ColRange>(
1476 self,
1477 row: RowRange,
1478 col: ColRange,
1479 ) -> <MatRef<'a, T, Rows, Cols, RStride, CStride> as MatIndex<
1480 RowRange,
1481 ColRange,
1482 >>::Target
1483 where
1484 MatRef<'a, T, Rows, Cols, RStride, CStride>:
1485 MatIndex<RowRange, ColRange>,
1486 {
1487 <MatRef<'a, T, Rows, Cols, RStride, CStride> as MatIndex<
1488 RowRange,
1489 ColRange,
1490 >>::get(self, row, col)
1491 }
1492
1493 #[track_caller]
1495 #[inline]
1496 pub fn get_r<RowRange>(
1497 self,
1498 row: RowRange,
1499 ) -> <MatRef<'a, T, Rows, Cols, RStride, CStride> as MatIndex<
1500 RowRange,
1501 core::ops::RangeFull,
1502 >>::Target
1503 where
1504 MatRef<'a, T, Rows, Cols, RStride, CStride>:
1505 MatIndex<RowRange, core::ops::RangeFull>,
1506 {
1507 <MatRef<'a, T, Rows, Cols, RStride, CStride> as MatIndex<
1508 RowRange,
1509 core::ops::RangeFull,
1510 >>::get(self, row, ..)
1511 }
1512
1513 #[track_caller]
1515 #[inline]
1516 pub fn get_c<ColRange>(
1517 self,
1518 col: ColRange,
1519 ) -> <MatRef<'a, T, Rows, Cols, RStride, CStride> as MatIndex<
1520 core::ops::RangeFull,
1521 ColRange,
1522 >>::Target
1523 where
1524 MatRef<'a, T, Rows, Cols, RStride, CStride>:
1525 MatIndex<core::ops::RangeFull, ColRange>,
1526 {
1527 <MatRef<'a, T, Rows, Cols, RStride, CStride> as MatIndex<
1528 core::ops::RangeFull,
1529 ColRange,
1530 >>::get(self, .., col)
1531 }
1532
1533 #[track_caller]
1542 #[inline]
1543 pub unsafe fn get_unchecked<RowRange, ColRange>(
1544 self,
1545 row: RowRange,
1546 col: ColRange,
1547 ) -> <MatRef<'a, T, Rows, Cols, RStride, CStride> as MatIndex<
1548 RowRange,
1549 ColRange,
1550 >>::Target
1551 where
1552 MatRef<'a, T, Rows, Cols, RStride, CStride>:
1553 MatIndex<RowRange, ColRange>,
1554 {
1555 unsafe {
1556 <MatRef<'a, T, Rows, Cols, RStride, CStride> as MatIndex<
1557 RowRange,
1558 ColRange,
1559 >>::get_unchecked(self, row, col)
1560 }
1561 }
1562
1563 #[inline]
1564 pub(crate) fn __at(self, (i, j): (Idx<Rows>, Idx<Cols>)) -> &'a T {
1565 self.at(i, j)
1566 }
1567}
1568impl<
1569 T,
1570 Rows: Shape,
1571 Cols: Shape,
1572 RStride: Stride,
1573 CStride: Stride,
1574 Inner: for<'short> Reborrow<
1575 'short,
1576 Target = Ref<'short, T, Rows, Cols, RStride, CStride>,
1577 >,
1578> generic::Mat<Inner>
1579{
1580 #[inline]
1582 pub fn as_ref(&self) -> MatRef<'_, T, Rows, Cols, RStride, CStride> {
1583 self.rb()
1584 }
1585
1586 #[inline]
1588 pub fn cloned(&self) -> Mat<T, Rows, Cols>
1589 where
1590 T: Clone,
1591 {
1592 fn imp<'M, 'N, T: Clone, RStride: Stride, CStride: Stride>(
1593 this: MatRef<'_, T, Dim<'M>, Dim<'N>, RStride, CStride>,
1594 ) -> Mat<T, Dim<'M>, Dim<'N>> {
1595 Mat::from_fn(this.nrows(), this.ncols(), |i, j| {
1596 this.at(i, j).clone()
1597 })
1598 }
1599 let this = self.rb();
1600 with_dim!(M, this.nrows().unbound());
1601 with_dim!(N, this.ncols().unbound());
1602 imp(this.as_shape(M, N)).into_shape(this.nrows(), this.ncols())
1603 }
1604
1605 #[inline]
1608 pub fn to_owned(&self) -> Mat<T::Canonical, Rows, Cols>
1609 where
1610 T: Conjugate,
1611 {
1612 fn imp<'M, 'N, T, RStride: Stride, CStride: Stride>(
1613 this: MatRef<'_, T, Dim<'M>, Dim<'N>, RStride, CStride>,
1614 ) -> Mat<T::Canonical, Dim<'M>, Dim<'N>>
1615 where
1616 T: Conjugate,
1617 {
1618 let src = this.canonical();
1632 if T::IS_CANONICAL
1633 && src.row_stride().element_stride().unsigned_abs() != 1
1634 {
1635 let mut out = Mat::<T::Canonical, Dim<'M>, Dim<'N>>::zeros(
1636 this.nrows(),
1637 this.ncols(),
1638 );
1639 crate::linalg::copy_across_layouts(
1640 out.as_mut().as_dyn_stride_mut().as_dyn_mut(),
1641 src.as_dyn_stride().as_dyn(),
1642 crate::Par::Seq,
1643 );
1644 return out;
1645 }
1646 Mat::from_fn(this.nrows(), this.ncols(), |i, j| {
1647 Conj::apply::<T>(this.at(i, j))
1648 })
1649 }
1650 let this = self.rb();
1651 with_dim!(M, this.nrows().unbound());
1652 with_dim!(N, this.ncols().unbound());
1653 imp(this.as_shape(M, N)).into_shape(this.nrows(), this.ncols())
1654 }
1655
1656 #[inline]
1658 pub fn norm_max(&self) -> Real<T>
1659 where
1660 T: Conjugate,
1661 {
1662 linalg::reductions::norm_max::norm_max(
1663 self.rb().canonical().as_dyn_stride().as_dyn(),
1664 )
1665 }
1666
1667 #[inline]
1669 pub fn norm_l2(&self) -> Real<T>
1670 where
1671 T: Conjugate,
1672 {
1673 linalg::reductions::norm_l2::norm_l2(
1674 self.rb().canonical().as_dyn_stride().as_dyn(),
1675 )
1676 }
1677
1678 #[inline]
1680 pub fn squared_norm_l2(&self) -> Real<T>
1681 where
1682 T: Conjugate,
1683 {
1684 linalg::reductions::norm_l2_sqr::norm_l2_sqr(
1685 self.rb().canonical().as_dyn_stride().as_dyn(),
1686 )
1687 }
1688
1689 #[inline]
1691 pub fn norm_l1(&self) -> Real<T>
1692 where
1693 T: Conjugate,
1694 {
1695 linalg::reductions::norm_l1::norm_l1(
1696 self.rb().canonical().as_dyn_stride().as_dyn(),
1697 )
1698 }
1699
1700 #[inline]
1702 pub fn sum(&self) -> T::Canonical
1703 where
1704 T: Conjugate,
1705 {
1706 let val = linalg::reductions::sum::sum(
1707 self.rb().canonical().as_dyn_stride().as_dyn(),
1708 );
1709 if const { Conj::get::<T>().is_conj() } {
1710 val.conj()
1711 } else {
1712 val
1713 }
1714 }
1715
1716 #[inline]
1718 pub fn determinant(&self, par: Par<'_>) -> T::Canonical
1719 where
1720 T: Conjugate,
1721 {
1722 let det = linalg::reductions::determinant::determinant(
1723 self.rb().canonical().as_dyn_stride().as_dyn(),
1724 par,
1725 );
1726 if const { T::IS_CANONICAL } {
1727 det
1728 } else {
1729 det.conj()
1730 }
1731 }
1732
1733 #[inline]
1768 pub fn kron(
1769 &self,
1770 rhs: impl AsMatRef<T: Conjugate<Canonical = T::Canonical>>,
1771 ) -> Mat<T::Canonical>
1772 where
1773 T: Conjugate,
1774 {
1775 fn imp<T: ComplexField>(
1776 lhs: MatRef<'_, impl Conjugate<Canonical = T>>,
1777 rhs: MatRef<'_, impl Conjugate<Canonical = T>>,
1778 ) -> Mat<T> {
1779 let mut out = Mat::zeros(
1780 lhs.nrows() * rhs.nrows(),
1781 lhs.ncols() * rhs.ncols(),
1782 );
1783 linalg::kron::kron(out.rb_mut(), lhs, rhs);
1784 out
1785 }
1786 imp(
1787 self.rb().as_dyn().as_dyn_stride(),
1788 rhs.as_mat_ref().as_dyn().as_dyn_stride(),
1789 )
1790 }
1791
1792 #[inline]
1795 pub fn is_all_finite(&self) -> bool
1796 where
1797 T: Conjugate,
1798 {
1799 fn imp<T: ComplexField>(A: MatRef<'_, T>) -> bool {
1800 with_dim!({
1801 let M = A.nrows();
1802 let N = A.ncols();
1803 });
1804 let A = A.as_shape(M, N);
1805 for j in N.indices() {
1806 for i in M.indices() {
1807 if !A[(i, j)].is_finite() {
1808 return false;
1809 }
1810 }
1811 }
1812 true
1813 }
1814 imp(self.rb().as_dyn().as_dyn_stride().canonical())
1815 }
1816
1817 #[inline]
1820 pub fn is_identity(&self) -> bool
1821 where
1822 T: Conjugate,
1823 {
1824 fn imp<T: ComplexField>(A: MatRef<'_, T>) -> bool {
1825 with_dim!({
1826 let M = A.nrows();
1827 let N = A.ncols();
1828 });
1829 let A = A.as_shape(M, N);
1830 for j in N.indices() {
1831 for i in M.indices() {
1832 if *i == *j {
1833 if A[(i, j)] != one() {
1834 return false;
1835 }
1836 } else {
1837 if A[(i, j)] != zero() {
1838 return false;
1839 }
1840 }
1841 }
1842 }
1843 true
1844 }
1845 imp(self.rb().as_dyn().as_dyn_stride().canonical())
1846 }
1847
1848 #[inline]
1851 pub fn has_nan(&self) -> bool
1852 where
1853 T: Conjugate,
1854 {
1855 fn imp<T: ComplexField>(A: MatRef<'_, T>) -> bool {
1856 with_dim!({
1857 let M = A.nrows();
1858 let N = A.ncols();
1859 });
1860 let A = A.as_shape(M, N);
1861 for j in N.indices() {
1862 for i in M.indices() {
1863 if A[(i, j)].is_nan() {
1864 return true;
1865 }
1866 }
1867 }
1868 false
1869 }
1870 imp(self.rb().as_dyn().as_dyn_stride().canonical())
1871 }
1872}
1873impl<'a, T, Dim: Shape, RStride: Stride, CStride: Stride>
1874 MatRef<'a, T, Dim, Dim, RStride, CStride>
1875{
1876 #[inline]
1878 pub fn diagonal(self) -> DiagRef<'a, T, Dim, isize> {
1879 let k = Ord::min(self.nrows(), self.ncols());
1880 DiagRef {
1881 0: crate::diag::Ref {
1882 inner: unsafe {
1883 ColRef::from_raw_parts(
1884 self.as_ptr(),
1885 k,
1886 self.row_stride().element_stride()
1887 + self.col_stride().element_stride(),
1888 )
1889 },
1890 },
1891 }
1892 }
1893}
1894impl<'ROWS, 'COLS, 'a, T, RStride: Stride, CStride: Stride>
1895 MatRef<'a, T, Dim<'ROWS>, Dim<'COLS>, RStride, CStride>
1896{
1897 #[doc(hidden)]
1898 #[inline]
1899 pub fn split_with<'TOP, 'BOT, 'LEFT, 'RIGHT>(
1900 self,
1901 row: Partition<'TOP, 'BOT, 'ROWS>,
1902 col: Partition<'LEFT, 'RIGHT, 'COLS>,
1903 ) -> (
1904 MatRef<'a, T, Dim<'TOP>, Dim<'LEFT>, RStride, CStride>,
1905 MatRef<'a, T, Dim<'TOP>, Dim<'RIGHT>, RStride, CStride>,
1906 MatRef<'a, T, Dim<'BOT>, Dim<'LEFT>, RStride, CStride>,
1907 MatRef<'a, T, Dim<'BOT>, Dim<'RIGHT>, RStride, CStride>,
1908 ) {
1909 let (a, b, c, d) = self.split_at(row.midpoint(), col.midpoint());
1910 (
1911 a.as_shape(row.head, col.head),
1912 b.as_shape(row.head, col.tail),
1913 c.as_shape(row.tail, col.head),
1914 d.as_shape(row.tail, col.tail),
1915 )
1916 }
1917}
1918impl<'ROWS, 'a, T, Cols: Shape, RStride: Stride, CStride: Stride>
1919 MatRef<'a, T, Dim<'ROWS>, Cols, RStride, CStride>
1920{
1921 #[doc(hidden)]
1922 #[inline]
1923 pub fn split_rows_with<'TOP, 'BOT>(
1924 self,
1925 row: Partition<'TOP, 'BOT, 'ROWS>,
1926 ) -> (
1927 MatRef<'a, T, Dim<'TOP>, Cols, RStride, CStride>,
1928 MatRef<'a, T, Dim<'BOT>, Cols, RStride, CStride>,
1929 ) {
1930 let (a, b) = self.split_at_row(row.midpoint());
1931 (a.as_row_shape(row.head), b.as_row_shape(row.tail))
1932 }
1933}
1934impl<'COLS, 'a, T, Rows: Shape, RStride: Stride, CStride: Stride>
1935 MatRef<'a, T, Rows, Dim<'COLS>, RStride, CStride>
1936{
1937 #[doc(hidden)]
1938 #[inline]
1939 pub fn split_cols_with<'LEFT, 'RIGHT>(
1940 self,
1941 col: Partition<'LEFT, 'RIGHT, 'COLS>,
1942 ) -> (
1943 MatRef<'a, T, Rows, Dim<'LEFT>, RStride, CStride>,
1944 MatRef<'a, T, Rows, Dim<'RIGHT>, RStride, CStride>,
1945 ) {
1946 let (a, b) = self.split_at_col(col.midpoint());
1947 (a.as_col_shape(col.head), b.as_col_shape(col.tail))
1948 }
1949}
1950impl<
1951 'a,
1952 T: core::fmt::Debug,
1953 Rows: Shape,
1954 Cols: Shape,
1955 RStride: Stride,
1956 CStride: Stride,
1957> core::fmt::Debug for Ref<'a, T, Rows, Cols, RStride, CStride>
1958{
1959 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1960 fn imp<'M, 'N, T: core::fmt::Debug>(
1961 this: MatRef<'_, T, Dim<'M>, Dim<'N>>,
1962 f: &mut core::fmt::Formatter<'_>,
1963 ) -> core::fmt::Result {
1964 writeln!(f, "[")?;
1965 for i in this.nrows().indices() {
1966 this.row(i).fmt(f)?;
1967 f.write_str(",\n")?;
1968 }
1969 write!(f, "]")
1970 }
1971 let this = generic::Mat::from_inner_ref(self);
1972 with_dim!(M, this.nrows().unbound());
1973 with_dim!(N, this.ncols().unbound());
1974 imp(this.as_shape(M, N).as_dyn_stride(), f)
1975 }
1976}
1977impl<'a, T: RealField> MatRef<'a, T, usize, usize> {
1978 pub(crate) fn internal_max(self) -> Option<T> {
1979 if self.nrows().unbound() == 0 || self.ncols().unbound() == 0 {
1980 return None;
1981 }
1982 let mut max_val = self.get(0, 0);
1983 let this = if self.row_stride().unsigned_abs() == 1 {
1984 self.transpose()
1985 } else {
1986 self
1987 };
1988 let this = if this.col_stride() > 0 {
1989 this
1990 } else {
1991 this.reverse_cols()
1992 };
1993 this.row_iter().for_each(|row| {
1994 row.iter().for_each(|val| {
1995 if val > max_val {
1996 max_val = &val;
1997 }
1998 });
1999 });
2000 Some((*max_val).clone())
2001 }
2002
2003 pub(crate) fn internal_min(self) -> Option<T> {
2004 if self.nrows().unbound() == 0 || self.ncols().unbound() == 0 {
2005 return None;
2006 }
2007 let mut min_val = self.get(0, 0);
2008 let this = if self.row_stride().unsigned_abs() == 1 {
2009 self.transpose()
2010 } else {
2011 self
2012 };
2013 let this = if this.col_stride() > 0 {
2014 this
2015 } else {
2016 this.reverse_cols()
2017 };
2018 this.row_iter().for_each(|row| {
2019 row.iter().for_each(|val| {
2020 if val < min_val {
2021 min_val = &val;
2022 }
2023 });
2024 });
2025 Some((*min_val).clone())
2026 }
2027}
2028impl<'a, T: RealField, Rows: Shape, Cols: Shape> MatRef<'a, T, Rows, Cols> {
2029 pub fn max(self) -> Option<T> {
2046 MatRef::internal_max(self.as_dyn())
2047 }
2048
2049 pub fn min(self) -> Option<T> {
2066 MatRef::internal_min(self.as_dyn())
2067 }
2068}
2069#[cfg(test)]
2070mod tests {
2071 use super::*;
2072 #[test]
2073 fn test_min() {
2074 let m = mat![[1.0, 5.0, 3.0], [4.0, 2.0, 9.0], [7.0, 8.0, 6.0],];
2075 assert_eq!(m.as_ref().min(), Some(1.0));
2076 let empty: Mat<f64> = Mat::new();
2077 assert_eq!(empty.as_ref().min(), None);
2078 }
2079 #[test]
2080 fn test_max() {
2081 let m = mat![[1.0, 5.0, 3.0], [4.0, 2.0, 9.0], [7.0, 8.0, 6.0],];
2082 assert_eq!(m.as_ref().max(), Some(9.0));
2083 let empty: Mat<f64> = Mat::new();
2084 assert_eq!(empty.as_ref().max(), None);
2085 }
2086 #[test]
2087 fn test_cloned_does_not_replicate_the_first_heap_value() {
2088 use std::{cell::Cell, rc::Rc};
2089 struct Value {
2090 text: String,
2091 clones: Rc<Cell<usize>>,
2092 }
2093 impl Clone for Value {
2094 fn clone(&self) -> Self {
2095 self.clones.set(self.clones.get() + 1);
2096 Self {
2097 text: self.text.clone(),
2098 clones: self.clones.clone(),
2099 }
2100 }
2101 }
2102 let source: Vec<_> = (0..6)
2103 .map(|i| Value {
2104 text: if i == 0 {
2105 "x".repeat(1024)
2106 } else {
2107 String::new()
2108 },
2109 clones: Rc::new(Cell::new(0)),
2110 })
2111 .collect();
2112 let view = MatRef::from_row_major_slice(&source, 2, 3);
2113 let copied = view.cloned();
2114 for i in 0..2 {
2115 for j in 0..3 {
2116 let original = &source[3 * i + j];
2117 assert_eq!(copied[(i, j)].text, original.text);
2118 assert_eq!(original.clones.get(), 1);
2119 }
2120 }
2121 }
2122
2123 #[test]
2125 fn test_cloned_from_a_strided_source() {
2126 fn check(m: usize, n: usize, (rs, cs): (isize, isize)) {
2127 let span = if m == 0 || n == 0 {
2131 0
2132 } else {
2133 (m - 1) * rs.unsigned_abs() + (n - 1) * cs.unsigned_abs() + 1
2134 };
2135 let raw: Vec<f64> = (0..span).map(|k| (k % 37) as f64 * 0.5 - 3.0).collect();
2136 let base = if m == 0 || n == 0 {
2137 0
2138 } else {
2139 (if rs < 0 { (m - 1) * rs.unsigned_abs() } else { 0 })
2140 + (if cs < 0 { (n - 1) * cs.unsigned_abs() } else { 0 })
2141 };
2142 let src = unsafe {
2143 MatRef::from_raw_parts(
2144 raw.as_ptr().add(base),
2145 m,
2146 n,
2147 rs,
2148 cs,
2149 )
2150 };
2151 let expected = Mat::from_fn(m, n, |i, j| src.at(i, j).clone());
2152 let got = src.cloned();
2153 if got.nrows() != m || got.ncols() != n {
2154 panic!("cloned {m}x{n}: shape is {}x{}", got.nrows(), got.ncols());
2155 }
2156 for j in 0..n {
2157 for i in 0..m {
2158 if got[(i, j)] != expected[(i, j)] {
2159 panic!(
2160 "cloned {m}x{n} strides {rs}x{cs}: ({i}, {j}) is {} against {}",
2161 got[(i, j)],
2162 expected[(i, j)]
2163 );
2164 }
2165 }
2166 }
2167 }
2168 for (m, n) in [
2169 (0, 0),
2170 (1, 1),
2171 (1, 5),
2172 (5, 1),
2173 (16, 16),
2174 (17, 15),
2175 (15, 17),
2176 (64, 3),
2177 (3, 64),
2178 (65, 33),
2179 ] {
2180 check(m, n, (n as isize, 1));
2181 check(m, n, (1, m as isize));
2182 check(m, n, (2 * n as isize, 3));
2183 check(m, n, (-(n as isize), 1));
2184 }
2185 }
2186}