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) -> 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 );
1725 if const { T::IS_CANONICAL } {
1726 det
1727 } else {
1728 det.conj()
1729 }
1730 }
1731
1732 #[inline]
1767 pub fn kron(
1768 &self,
1769 rhs: impl AsMatRef<T: Conjugate<Canonical = T::Canonical>>,
1770 ) -> Mat<T::Canonical>
1771 where
1772 T: Conjugate,
1773 {
1774 fn imp<T: ComplexField>(
1775 lhs: MatRef<'_, impl Conjugate<Canonical = T>>,
1776 rhs: MatRef<'_, impl Conjugate<Canonical = T>>,
1777 ) -> Mat<T> {
1778 let mut out = Mat::zeros(
1779 lhs.nrows() * rhs.nrows(),
1780 lhs.ncols() * rhs.ncols(),
1781 );
1782 linalg::kron::kron(out.rb_mut(), lhs, rhs);
1783 out
1784 }
1785 imp(
1786 self.rb().as_dyn().as_dyn_stride(),
1787 rhs.as_mat_ref().as_dyn().as_dyn_stride(),
1788 )
1789 }
1790
1791 #[inline]
1794 pub fn is_all_finite(&self) -> bool
1795 where
1796 T: Conjugate,
1797 {
1798 fn imp<T: ComplexField>(A: MatRef<'_, T>) -> bool {
1799 with_dim!({
1800 let M = A.nrows();
1801 let N = A.ncols();
1802 });
1803 let A = A.as_shape(M, N);
1804 for j in N.indices() {
1805 for i in M.indices() {
1806 if !A[(i, j)].is_finite() {
1807 return false;
1808 }
1809 }
1810 }
1811 true
1812 }
1813 imp(self.rb().as_dyn().as_dyn_stride().canonical())
1814 }
1815
1816 #[inline]
1819 pub fn is_identity(&self) -> bool
1820 where
1821 T: Conjugate,
1822 {
1823 fn imp<T: ComplexField>(A: MatRef<'_, T>) -> bool {
1824 with_dim!({
1825 let M = A.nrows();
1826 let N = A.ncols();
1827 });
1828 let A = A.as_shape(M, N);
1829 for j in N.indices() {
1830 for i in M.indices() {
1831 if *i == *j {
1832 if A[(i, j)] != one() {
1833 return false;
1834 }
1835 } else {
1836 if A[(i, j)] != zero() {
1837 return false;
1838 }
1839 }
1840 }
1841 }
1842 true
1843 }
1844 imp(self.rb().as_dyn().as_dyn_stride().canonical())
1845 }
1846
1847 #[inline]
1850 pub fn has_nan(&self) -> bool
1851 where
1852 T: Conjugate,
1853 {
1854 fn imp<T: ComplexField>(A: MatRef<'_, T>) -> bool {
1855 with_dim!({
1856 let M = A.nrows();
1857 let N = A.ncols();
1858 });
1859 let A = A.as_shape(M, N);
1860 for j in N.indices() {
1861 for i in M.indices() {
1862 if A[(i, j)].is_nan() {
1863 return true;
1864 }
1865 }
1866 }
1867 false
1868 }
1869 imp(self.rb().as_dyn().as_dyn_stride().canonical())
1870 }
1871}
1872impl<'a, T, Dim: Shape, RStride: Stride, CStride: Stride>
1873 MatRef<'a, T, Dim, Dim, RStride, CStride>
1874{
1875 #[inline]
1877 pub fn diagonal(self) -> DiagRef<'a, T, Dim, isize> {
1878 let k = Ord::min(self.nrows(), self.ncols());
1879 DiagRef {
1880 0: crate::diag::Ref {
1881 inner: unsafe {
1882 ColRef::from_raw_parts(
1883 self.as_ptr(),
1884 k,
1885 self.row_stride().element_stride()
1886 + self.col_stride().element_stride(),
1887 )
1888 },
1889 },
1890 }
1891 }
1892}
1893impl<'ROWS, 'COLS, 'a, T, RStride: Stride, CStride: Stride>
1894 MatRef<'a, T, Dim<'ROWS>, Dim<'COLS>, RStride, CStride>
1895{
1896 #[doc(hidden)]
1897 #[inline]
1898 pub fn split_with<'TOP, 'BOT, 'LEFT, 'RIGHT>(
1899 self,
1900 row: Partition<'TOP, 'BOT, 'ROWS>,
1901 col: Partition<'LEFT, 'RIGHT, 'COLS>,
1902 ) -> (
1903 MatRef<'a, T, Dim<'TOP>, Dim<'LEFT>, RStride, CStride>,
1904 MatRef<'a, T, Dim<'TOP>, Dim<'RIGHT>, RStride, CStride>,
1905 MatRef<'a, T, Dim<'BOT>, Dim<'LEFT>, RStride, CStride>,
1906 MatRef<'a, T, Dim<'BOT>, Dim<'RIGHT>, RStride, CStride>,
1907 ) {
1908 let (a, b, c, d) = self.split_at(row.midpoint(), col.midpoint());
1909 (
1910 a.as_shape(row.head, col.head),
1911 b.as_shape(row.head, col.tail),
1912 c.as_shape(row.tail, col.head),
1913 d.as_shape(row.tail, col.tail),
1914 )
1915 }
1916}
1917impl<'ROWS, 'a, T, Cols: Shape, RStride: Stride, CStride: Stride>
1918 MatRef<'a, T, Dim<'ROWS>, Cols, RStride, CStride>
1919{
1920 #[doc(hidden)]
1921 #[inline]
1922 pub fn split_rows_with<'TOP, 'BOT>(
1923 self,
1924 row: Partition<'TOP, 'BOT, 'ROWS>,
1925 ) -> (
1926 MatRef<'a, T, Dim<'TOP>, Cols, RStride, CStride>,
1927 MatRef<'a, T, Dim<'BOT>, Cols, RStride, CStride>,
1928 ) {
1929 let (a, b) = self.split_at_row(row.midpoint());
1930 (a.as_row_shape(row.head), b.as_row_shape(row.tail))
1931 }
1932}
1933impl<'COLS, 'a, T, Rows: Shape, RStride: Stride, CStride: Stride>
1934 MatRef<'a, T, Rows, Dim<'COLS>, RStride, CStride>
1935{
1936 #[doc(hidden)]
1937 #[inline]
1938 pub fn split_cols_with<'LEFT, 'RIGHT>(
1939 self,
1940 col: Partition<'LEFT, 'RIGHT, 'COLS>,
1941 ) -> (
1942 MatRef<'a, T, Rows, Dim<'LEFT>, RStride, CStride>,
1943 MatRef<'a, T, Rows, Dim<'RIGHT>, RStride, CStride>,
1944 ) {
1945 let (a, b) = self.split_at_col(col.midpoint());
1946 (a.as_col_shape(col.head), b.as_col_shape(col.tail))
1947 }
1948}
1949impl<
1950 'a,
1951 T: core::fmt::Debug,
1952 Rows: Shape,
1953 Cols: Shape,
1954 RStride: Stride,
1955 CStride: Stride,
1956> core::fmt::Debug for Ref<'a, T, Rows, Cols, RStride, CStride>
1957{
1958 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1959 fn imp<'M, 'N, T: core::fmt::Debug>(
1960 this: MatRef<'_, T, Dim<'M>, Dim<'N>>,
1961 f: &mut core::fmt::Formatter<'_>,
1962 ) -> core::fmt::Result {
1963 writeln!(f, "[")?;
1964 for i in this.nrows().indices() {
1965 this.row(i).fmt(f)?;
1966 f.write_str(",\n")?;
1967 }
1968 write!(f, "]")
1969 }
1970 let this = generic::Mat::from_inner_ref(self);
1971 with_dim!(M, this.nrows().unbound());
1972 with_dim!(N, this.ncols().unbound());
1973 imp(this.as_shape(M, N).as_dyn_stride(), f)
1974 }
1975}
1976impl<'a, T: RealField> MatRef<'a, T, usize, usize> {
1977 pub(crate) fn internal_max(self) -> Option<T> {
1978 if self.nrows().unbound() == 0 || self.ncols().unbound() == 0 {
1979 return None;
1980 }
1981 let mut max_val = self.get(0, 0);
1982 let this = if self.row_stride().unsigned_abs() == 1 {
1983 self.transpose()
1984 } else {
1985 self
1986 };
1987 let this = if this.col_stride() > 0 {
1988 this
1989 } else {
1990 this.reverse_cols()
1991 };
1992 this.row_iter().for_each(|row| {
1993 row.iter().for_each(|val| {
1994 if val > max_val {
1995 max_val = &val;
1996 }
1997 });
1998 });
1999 Some((*max_val).clone())
2000 }
2001
2002 pub(crate) fn internal_min(self) -> Option<T> {
2003 if self.nrows().unbound() == 0 || self.ncols().unbound() == 0 {
2004 return None;
2005 }
2006 let mut min_val = self.get(0, 0);
2007 let this = if self.row_stride().unsigned_abs() == 1 {
2008 self.transpose()
2009 } else {
2010 self
2011 };
2012 let this = if this.col_stride() > 0 {
2013 this
2014 } else {
2015 this.reverse_cols()
2016 };
2017 this.row_iter().for_each(|row| {
2018 row.iter().for_each(|val| {
2019 if val < min_val {
2020 min_val = &val;
2021 }
2022 });
2023 });
2024 Some((*min_val).clone())
2025 }
2026}
2027impl<'a, T: RealField, Rows: Shape, Cols: Shape> MatRef<'a, T, Rows, Cols> {
2028 pub fn max(self) -> Option<T> {
2045 MatRef::internal_max(self.as_dyn())
2046 }
2047
2048 pub fn min(self) -> Option<T> {
2065 MatRef::internal_min(self.as_dyn())
2066 }
2067}
2068#[cfg(test)]
2069mod tests {
2070 use super::*;
2071 #[test]
2072 fn test_min() {
2073 let m = mat![[1.0, 5.0, 3.0], [4.0, 2.0, 9.0], [7.0, 8.0, 6.0],];
2074 assert_eq!(m.as_ref().min(), Some(1.0));
2075 let empty: Mat<f64> = Mat::new();
2076 assert_eq!(empty.as_ref().min(), None);
2077 }
2078 #[test]
2079 fn test_max() {
2080 let m = mat![[1.0, 5.0, 3.0], [4.0, 2.0, 9.0], [7.0, 8.0, 6.0],];
2081 assert_eq!(m.as_ref().max(), Some(9.0));
2082 let empty: Mat<f64> = Mat::new();
2083 assert_eq!(empty.as_ref().max(), None);
2084 }
2085 #[test]
2086 fn test_cloned_does_not_replicate_the_first_heap_value() {
2087 use std::{cell::Cell, rc::Rc};
2088 struct Value {
2089 text: String,
2090 clones: Rc<Cell<usize>>,
2091 }
2092 impl Clone for Value {
2093 fn clone(&self) -> Self {
2094 self.clones.set(self.clones.get() + 1);
2095 Self {
2096 text: self.text.clone(),
2097 clones: self.clones.clone(),
2098 }
2099 }
2100 }
2101 let source: Vec<_> = (0..6)
2102 .map(|i| Value {
2103 text: if i == 0 {
2104 "x".repeat(1024)
2105 } else {
2106 String::new()
2107 },
2108 clones: Rc::new(Cell::new(0)),
2109 })
2110 .collect();
2111 let view = MatRef::from_row_major_slice(&source, 2, 3);
2112 let copied = view.cloned();
2113 for i in 0..2 {
2114 for j in 0..3 {
2115 let original = &source[3 * i + j];
2116 assert_eq!(copied[(i, j)].text, original.text);
2117 assert_eq!(original.clones.get(), 1);
2118 }
2119 }
2120 }
2121
2122 #[test]
2124 fn test_cloned_from_a_strided_source() {
2125 fn check(m: usize, n: usize, (rs, cs): (isize, isize)) {
2126 let span = if m == 0 || n == 0 {
2130 0
2131 } else {
2132 (m - 1) * rs.unsigned_abs() + (n - 1) * cs.unsigned_abs() + 1
2133 };
2134 let raw: Vec<f64> = (0..span).map(|k| (k % 37) as f64 * 0.5 - 3.0).collect();
2135 let base = if m == 0 || n == 0 {
2136 0
2137 } else {
2138 (if rs < 0 { (m - 1) * rs.unsigned_abs() } else { 0 })
2139 + (if cs < 0 { (n - 1) * cs.unsigned_abs() } else { 0 })
2140 };
2141 let src = unsafe {
2142 MatRef::from_raw_parts(
2143 raw.as_ptr().add(base),
2144 m,
2145 n,
2146 rs,
2147 cs,
2148 )
2149 };
2150 let expected = Mat::from_fn(m, n, |i, j| src.at(i, j).clone());
2151 let got = src.cloned();
2152 if got.nrows() != m || got.ncols() != n {
2153 panic!("cloned {m}x{n}: shape is {}x{}", got.nrows(), got.ncols());
2154 }
2155 for j in 0..n {
2156 for i in 0..m {
2157 if got[(i, j)] != expected[(i, j)] {
2158 panic!(
2159 "cloned {m}x{n} strides {rs}x{cs}: ({i}, {j}) is {} against {}",
2160 got[(i, j)],
2161 expected[(i, j)]
2162 );
2163 }
2164 }
2165 }
2166 }
2167 for (m, n) in [
2168 (0, 0),
2169 (1, 1),
2170 (1, 5),
2171 (5, 1),
2172 (16, 16),
2173 (17, 15),
2174 (15, 17),
2175 (64, 3),
2176 (3, 64),
2177 (65, 33),
2178 ] {
2179 check(m, n, (n as isize, 1));
2180 check(m, n, (1, m as isize));
2181 check(m, n, (2 * n as isize, 3));
2182 check(m, n, (-(n as isize), 1));
2183 }
2184 }
2185}