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 Mat::from_fn(this.nrows(), this.ncols(), |i, j| {
1619 Conj::apply::<T>(this.at(i, j))
1620 })
1621 }
1622 let this = self.rb();
1623 with_dim!(M, this.nrows().unbound());
1624 with_dim!(N, this.ncols().unbound());
1625 imp(this.as_shape(M, N)).into_shape(this.nrows(), this.ncols())
1626 }
1627
1628 #[inline]
1630 pub fn norm_max(&self) -> Real<T>
1631 where
1632 T: Conjugate,
1633 {
1634 linalg::reductions::norm_max::norm_max(
1635 self.rb().canonical().as_dyn_stride().as_dyn(),
1636 )
1637 }
1638
1639 #[inline]
1641 pub fn norm_l2(&self) -> Real<T>
1642 where
1643 T: Conjugate,
1644 {
1645 linalg::reductions::norm_l2::norm_l2(
1646 self.rb().canonical().as_dyn_stride().as_dyn(),
1647 )
1648 }
1649
1650 #[inline]
1652 pub fn squared_norm_l2(&self) -> Real<T>
1653 where
1654 T: Conjugate,
1655 {
1656 linalg::reductions::norm_l2_sqr::norm_l2_sqr(
1657 self.rb().canonical().as_dyn_stride().as_dyn(),
1658 )
1659 }
1660
1661 #[inline]
1663 pub fn norm_l1(&self) -> Real<T>
1664 where
1665 T: Conjugate,
1666 {
1667 linalg::reductions::norm_l1::norm_l1(
1668 self.rb().canonical().as_dyn_stride().as_dyn(),
1669 )
1670 }
1671
1672 #[inline]
1674 pub fn sum(&self) -> T::Canonical
1675 where
1676 T: Conjugate,
1677 {
1678 let val = linalg::reductions::sum::sum(
1679 self.rb().canonical().as_dyn_stride().as_dyn(),
1680 );
1681 if const { Conj::get::<T>().is_conj() } {
1682 val.conj()
1683 } else {
1684 val
1685 }
1686 }
1687
1688 #[inline]
1690 pub fn determinant(&self) -> T::Canonical
1691 where
1692 T: Conjugate,
1693 {
1694 let det = linalg::reductions::determinant::determinant(
1695 self.rb().canonical().as_dyn_stride().as_dyn(),
1696 );
1697 if const { T::IS_CANONICAL } {
1698 det
1699 } else {
1700 det.conj()
1701 }
1702 }
1703
1704 #[inline]
1739 pub fn kron(
1740 &self,
1741 rhs: impl AsMatRef<T: Conjugate<Canonical = T::Canonical>>,
1742 ) -> Mat<T::Canonical>
1743 where
1744 T: Conjugate,
1745 {
1746 fn imp<T: ComplexField>(
1747 lhs: MatRef<'_, impl Conjugate<Canonical = T>>,
1748 rhs: MatRef<'_, impl Conjugate<Canonical = T>>,
1749 ) -> Mat<T> {
1750 let mut out = Mat::zeros(
1751 lhs.nrows() * rhs.nrows(),
1752 lhs.ncols() * rhs.ncols(),
1753 );
1754 linalg::kron::kron(out.rb_mut(), lhs, rhs);
1755 out
1756 }
1757 imp(
1758 self.rb().as_dyn().as_dyn_stride(),
1759 rhs.as_mat_ref().as_dyn().as_dyn_stride(),
1760 )
1761 }
1762
1763 #[inline]
1766 pub fn is_all_finite(&self) -> bool
1767 where
1768 T: Conjugate,
1769 {
1770 fn imp<T: ComplexField>(A: MatRef<'_, T>) -> bool {
1771 with_dim!({
1772 let M = A.nrows();
1773 let N = A.ncols();
1774 });
1775 let A = A.as_shape(M, N);
1776 for j in N.indices() {
1777 for i in M.indices() {
1778 if !A[(i, j)].is_finite() {
1779 return false;
1780 }
1781 }
1782 }
1783 true
1784 }
1785 imp(self.rb().as_dyn().as_dyn_stride().canonical())
1786 }
1787
1788 #[inline]
1791 pub fn is_identity(&self) -> bool
1792 where
1793 T: Conjugate,
1794 {
1795 fn imp<T: ComplexField>(A: MatRef<'_, T>) -> bool {
1796 with_dim!({
1797 let M = A.nrows();
1798 let N = A.ncols();
1799 });
1800 let A = A.as_shape(M, N);
1801 for j in N.indices() {
1802 for i in M.indices() {
1803 if *i == *j {
1804 if A[(i, j)] != one() {
1805 return false;
1806 }
1807 } else {
1808 if A[(i, j)] != zero() {
1809 return false;
1810 }
1811 }
1812 }
1813 }
1814 true
1815 }
1816 imp(self.rb().as_dyn().as_dyn_stride().canonical())
1817 }
1818
1819 #[inline]
1822 pub fn has_nan(&self) -> bool
1823 where
1824 T: Conjugate,
1825 {
1826 fn imp<T: ComplexField>(A: MatRef<'_, T>) -> bool {
1827 with_dim!({
1828 let M = A.nrows();
1829 let N = A.ncols();
1830 });
1831 let A = A.as_shape(M, N);
1832 for j in N.indices() {
1833 for i in M.indices() {
1834 if A[(i, j)].is_nan() {
1835 return true;
1836 }
1837 }
1838 }
1839 false
1840 }
1841 imp(self.rb().as_dyn().as_dyn_stride().canonical())
1842 }
1843}
1844impl<'a, T, Dim: Shape, RStride: Stride, CStride: Stride>
1845 MatRef<'a, T, Dim, Dim, RStride, CStride>
1846{
1847 #[inline]
1849 pub fn diagonal(self) -> DiagRef<'a, T, Dim, isize> {
1850 let k = Ord::min(self.nrows(), self.ncols());
1851 DiagRef {
1852 0: crate::diag::Ref {
1853 inner: unsafe {
1854 ColRef::from_raw_parts(
1855 self.as_ptr(),
1856 k,
1857 self.row_stride().element_stride()
1858 + self.col_stride().element_stride(),
1859 )
1860 },
1861 },
1862 }
1863 }
1864}
1865impl<'ROWS, 'COLS, 'a, T, RStride: Stride, CStride: Stride>
1866 MatRef<'a, T, Dim<'ROWS>, Dim<'COLS>, RStride, CStride>
1867{
1868 #[doc(hidden)]
1869 #[inline]
1870 pub fn split_with<'TOP, 'BOT, 'LEFT, 'RIGHT>(
1871 self,
1872 row: Partition<'TOP, 'BOT, 'ROWS>,
1873 col: Partition<'LEFT, 'RIGHT, 'COLS>,
1874 ) -> (
1875 MatRef<'a, T, Dim<'TOP>, Dim<'LEFT>, RStride, CStride>,
1876 MatRef<'a, T, Dim<'TOP>, Dim<'RIGHT>, RStride, CStride>,
1877 MatRef<'a, T, Dim<'BOT>, Dim<'LEFT>, RStride, CStride>,
1878 MatRef<'a, T, Dim<'BOT>, Dim<'RIGHT>, RStride, CStride>,
1879 ) {
1880 let (a, b, c, d) = self.split_at(row.midpoint(), col.midpoint());
1881 (
1882 a.as_shape(row.head, col.head),
1883 b.as_shape(row.head, col.tail),
1884 c.as_shape(row.tail, col.head),
1885 d.as_shape(row.tail, col.tail),
1886 )
1887 }
1888}
1889impl<'ROWS, 'a, T, Cols: Shape, RStride: Stride, CStride: Stride>
1890 MatRef<'a, T, Dim<'ROWS>, Cols, RStride, CStride>
1891{
1892 #[doc(hidden)]
1893 #[inline]
1894 pub fn split_rows_with<'TOP, 'BOT>(
1895 self,
1896 row: Partition<'TOP, 'BOT, 'ROWS>,
1897 ) -> (
1898 MatRef<'a, T, Dim<'TOP>, Cols, RStride, CStride>,
1899 MatRef<'a, T, Dim<'BOT>, Cols, RStride, CStride>,
1900 ) {
1901 let (a, b) = self.split_at_row(row.midpoint());
1902 (a.as_row_shape(row.head), b.as_row_shape(row.tail))
1903 }
1904}
1905impl<'COLS, 'a, T, Rows: Shape, RStride: Stride, CStride: Stride>
1906 MatRef<'a, T, Rows, Dim<'COLS>, RStride, CStride>
1907{
1908 #[doc(hidden)]
1909 #[inline]
1910 pub fn split_cols_with<'LEFT, 'RIGHT>(
1911 self,
1912 col: Partition<'LEFT, 'RIGHT, 'COLS>,
1913 ) -> (
1914 MatRef<'a, T, Rows, Dim<'LEFT>, RStride, CStride>,
1915 MatRef<'a, T, Rows, Dim<'RIGHT>, RStride, CStride>,
1916 ) {
1917 let (a, b) = self.split_at_col(col.midpoint());
1918 (a.as_col_shape(col.head), b.as_col_shape(col.tail))
1919 }
1920}
1921impl<
1922 'a,
1923 T: core::fmt::Debug,
1924 Rows: Shape,
1925 Cols: Shape,
1926 RStride: Stride,
1927 CStride: Stride,
1928> core::fmt::Debug for Ref<'a, T, Rows, Cols, RStride, CStride>
1929{
1930 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1931 fn imp<'M, 'N, T: core::fmt::Debug>(
1932 this: MatRef<'_, T, Dim<'M>, Dim<'N>>,
1933 f: &mut core::fmt::Formatter<'_>,
1934 ) -> core::fmt::Result {
1935 writeln!(f, "[")?;
1936 for i in this.nrows().indices() {
1937 this.row(i).fmt(f)?;
1938 f.write_str(",\n")?;
1939 }
1940 write!(f, "]")
1941 }
1942 let this = generic::Mat::from_inner_ref(self);
1943 with_dim!(M, this.nrows().unbound());
1944 with_dim!(N, this.ncols().unbound());
1945 imp(this.as_shape(M, N).as_dyn_stride(), f)
1946 }
1947}
1948impl<'a, T: RealField> MatRef<'a, T, usize, usize> {
1949 pub(crate) fn internal_max(self) -> Option<T> {
1950 if self.nrows().unbound() == 0 || self.ncols().unbound() == 0 {
1951 return None;
1952 }
1953 let mut max_val = self.get(0, 0);
1954 let this = if self.row_stride().unsigned_abs() == 1 {
1955 self.transpose()
1956 } else {
1957 self
1958 };
1959 let this = if this.col_stride() > 0 {
1960 this
1961 } else {
1962 this.reverse_cols()
1963 };
1964 this.row_iter().for_each(|row| {
1965 row.iter().for_each(|val| {
1966 if val > max_val {
1967 max_val = &val;
1968 }
1969 });
1970 });
1971 Some((*max_val).clone())
1972 }
1973
1974 pub(crate) fn internal_min(self) -> Option<T> {
1975 if self.nrows().unbound() == 0 || self.ncols().unbound() == 0 {
1976 return None;
1977 }
1978 let mut min_val = self.get(0, 0);
1979 let this = if self.row_stride().unsigned_abs() == 1 {
1980 self.transpose()
1981 } else {
1982 self
1983 };
1984 let this = if this.col_stride() > 0 {
1985 this
1986 } else {
1987 this.reverse_cols()
1988 };
1989 this.row_iter().for_each(|row| {
1990 row.iter().for_each(|val| {
1991 if val < min_val {
1992 min_val = &val;
1993 }
1994 });
1995 });
1996 Some((*min_val).clone())
1997 }
1998}
1999impl<'a, T: RealField, Rows: Shape, Cols: Shape> MatRef<'a, T, Rows, Cols> {
2000 pub fn max(self) -> Option<T> {
2017 MatRef::internal_max(self.as_dyn())
2018 }
2019
2020 pub fn min(self) -> Option<T> {
2037 MatRef::internal_min(self.as_dyn())
2038 }
2039}
2040#[cfg(test)]
2041mod tests {
2042 use super::*;
2043 #[test]
2044 fn test_min() {
2045 let m = mat![[1.0, 5.0, 3.0], [4.0, 2.0, 9.0], [7.0, 8.0, 6.0],];
2046 assert_eq!(m.as_ref().min(), Some(1.0));
2047 let empty: Mat<f64> = Mat::new();
2048 assert_eq!(empty.as_ref().min(), None);
2049 }
2050 #[test]
2051 fn test_max() {
2052 let m = mat![[1.0, 5.0, 3.0], [4.0, 2.0, 9.0], [7.0, 8.0, 6.0],];
2053 assert_eq!(m.as_ref().max(), Some(9.0));
2054 let empty: Mat<f64> = Mat::new();
2055 assert_eq!(empty.as_ref().max(), None);
2056 }
2057}