Skip to main content

faer/mat/
matref.rs

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;
10/// see [`super::MatRef`]
11pub 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	/// equivalent to `MatRef::from_row_major_slice(array.as_flattened(), ROWS,
91	/// COLS)`
92	#[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	/// equivalent to `MatRef::from_column_major_slice(array.as_flattened(),
108	/// ROWS, COLS)`
109	#[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	/// creates a `1×1` view over the given element
125	#[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	/// creates a `ColRef` from a view over a single element, repeated
133	/// `nrows` times
134	#[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	/// creates a `RowRef` from a view over a single element, repeated
142	/// `ncols` times
143	#[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	/// creates a `MatRef` from a view over a single element, repeated
151	/// `nrows×ncols` times
152	#[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	/// creates a `MatRef` from a view over a single column, repeated
158	/// `ncols` times
159	#[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	/// creates a `MatRef` from a view over a single row, repeated
173	/// `nrows` times
174	#[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	/// creates a `MatRef` from slice views over the matrix data, and the matrix
188	/// dimensions. the data is interpreted in a column-major format, so that
189	/// the first chunk of `nrows` values from the slices goes in the first
190	/// column of the matrix, the second chunk of `nrows` values goes in the
191	/// second column, and so on
192	///
193	/// # panics
194	/// the function panics if any of the following conditions are violated:
195	/// * `nrows * ncols == slice.len()`
196	///
197	/// # example
198	/// ```
199	/// use faer::{MatRef, mat};
200	/// let slice = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0_f64];
201	/// let view = MatRef::from_column_major_slice(&slice, 3, 2);
202	/// let expected = mat![[1.0, 4.0], [2.0, 5.0], [3.0, 6.0]];
203	/// assert_eq!(expected, view);
204	/// ```
205	#[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	/// creates a `MatRef` from slice views over the matrix data, and the matrix
225	/// dimensions. the data is interpreted in a column-major format, where the
226	/// beginnings of two consecutive columns are separated by `col_stride`
227	/// elements
228	#[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	/// creates a `MatRef` from slice views over the matrix data, and the matrix
254	/// dimensions. the data is interpreted in a row-major format, so that the
255	/// first chunk of `ncols` values from the slices goes in the first column
256	/// of the matrix, the second chunk of `ncols` values goes in the second
257	/// column, and so on
258	///
259	/// # panics
260	/// the function panics if any of the following conditions are violated:
261	/// * `nrows * ncols == slice.len()`
262	///
263	/// # example
264	/// ```
265	/// use faer::{MatRef, mat};
266	/// let slice = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0_f64];
267	/// let view = MatRef::from_row_major_slice(&slice, 3, 2);
268	/// let expected = mat![[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]];
269	/// assert_eq!(expected, view);
270	/// ```
271	#[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	/// creates a `MatRef` from slice views over the matrix data, and the matrix
282	/// dimensions. the data is interpreted in a row-major format, where the
283	/// beginnings of two consecutive rows are separated by `row_stride`
284	/// elements
285	#[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	/// creates a `MatRef` from a pointer to the matrix data, dimensions, and
303	/// strides
304	///
305	/// the row (resp. column) stride is the offset from the memory address of a
306	/// given matrix element at index `(row: i, col: j)`, to the memory address
307	/// of the matrix element at index `(row: i + 1, col: 0)` (resp. `(row: 0,
308	/// col: i + 1)`). this offset is specified in number of elements, not in
309	/// bytes
310	///
311	/// # safety
312	/// the behavior is undefined if any of the following conditions are
313	/// violated:
314	/// * for each matrix unit, the entire memory region addressed by the matrix
315	///   must be contained
316	/// within a single allocation, accessible in its entirety by the
317	/// corresponding pointer in `ptr`
318	/// * for each matrix unit, the corresponding pointer must be properly
319	///   aligned,
320	/// even for a zero-sized matrix
321	/// * the values accessible by the matrix must be initialized at some point
322	///   before they are
323	/// read, or references to them are formed
324	/// * no mutable aliasing is allowed. in other words, none of the elements
325	///   accessible by any
326	/// matrix unit may be accessed for writes by any other means for the
327	/// duration of the lifetime `'a`
328	///
329	/// # example
330	///
331	/// ```
332	/// use faer::{MatRef, mat};
333	/// // row major matrix with 2 rows, 3 columns, with a column at the end that we want to skip.
334	/// // the row stride is the pointer offset from the address of 1.0 to the address of 4.0,
335	/// // which is 4
336	/// // the column stride is the pointer offset from the address of 1.0 to the address of 2.0,
337	/// // which is 1
338	/// let data = [[1.0, 2.0, 3.0, f64::NAN], [4.0, 5.0, 6.0, f64::NAN]];
339	/// let matrix = unsafe { MatRef::from_raw_parts(data.as_ptr() as *const f64, 2, 3, 4, 1) };
340	/// let expected = mat![[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]];
341	/// assert_eq!(expected.as_ref(), matrix);
342	/// ```
343	#[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	/// returns a pointer to the matrix data
365	#[inline]
366	pub fn as_ptr(&self) -> *const T {
367		self.imp.ptr.as_ptr() as *const T
368	}
369
370	/// returns the number of rows of the matrix
371	#[inline]
372	pub fn nrows(&self) -> Rows {
373		self.imp.nrows
374	}
375
376	/// returns the number of columns of the matrix
377	#[inline]
378	pub fn ncols(&self) -> Cols {
379		self.imp.ncols
380	}
381
382	/// returns the number of rows and columns of the matrix
383	#[inline]
384	pub fn shape(&self) -> (Rows, Cols) {
385		(self.nrows(), self.ncols())
386	}
387
388	/// returns the row stride of the matrix, specified in number of elements,
389	/// not in bytes
390	#[inline]
391	pub fn row_stride(&self) -> RStride {
392		self.imp.row_stride
393	}
394
395	/// returns the column stride of the matrix, specified in number of
396	/// elements, not in bytes
397	#[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	/// returns a raw pointer to the element at the given index
415	#[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	/// returns a raw pointer to the element at the given index, assuming the
431	/// provided index is within the matrix bounds
432	///
433	/// # safety
434	/// the behavior is undefined if any of the following conditions are
435	/// violated:
436	/// * `row < self.nrows()`
437	/// * `col < self.ncols()`
438	#[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	/// splits the matrix horizontally and vertically at the given index into
452	/// four corners and returns an array of each submatrix, in the following
453	/// order:
454	/// * top left
455	/// * top right
456	/// * bottom left
457	/// * bottom right
458	///
459	/// # safety
460	/// the function panics if any of the following conditions are violated:
461	/// * `row <= self.nrows()`
462	/// * `col <= self.ncols()`
463	#[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	/// splits the matrix horizontally at the given row into two parts and
517	/// returns an array of each submatrix, in the following order:
518	/// * top
519	/// * bottom
520	///
521	/// # panics
522	/// the function panics if the following condition is violated:
523	/// * `row <= self.nrows()`
524	#[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	/// splits the matrix vertically at the given column into two parts and
559	/// returns an array of each submatrix, in the following order:
560	/// * left
561	/// * right
562	///
563	/// # panics
564	/// the function panics if the following condition is violated:
565	/// * `col <= self.ncols()`
566	#[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	/// returns a view over the transpose of `self`
601	///
602	/// # example
603	/// ```
604	/// use faer::mat;
605	/// let matrix = mat![[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]];
606	/// let view = matrix.as_ref();
607	/// let transpose = view.transpose();
608	/// let expected = mat![[1.0, 4.0], [2.0, 5.0], [3.0, 6.0]];
609	/// assert_eq!(expected.as_ref(), transpose);
610	/// ```
611	#[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	/// returns a view over the conjugate of `self`
628	#[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	/// returns an unconjugated view over `self`
645	#[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	/// returns a view over the conjugate transpose of `self`.
675	#[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	/// returns a view over the `self`, with the rows in reversed order
701	///
702	/// # example
703	/// ```
704	/// use faer::mat;
705	/// let matrix = mat![[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]];
706	/// let view = matrix.as_ref();
707	/// let reversed_rows = view.reverse_rows();
708	/// let expected = mat![[4.0, 5.0, 6.0], [1.0, 2.0, 3.0]];
709	/// assert_eq!(expected.as_ref(), reversed_rows);
710	/// ```
711	#[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	/// returns a view over the `self`, with the columns in reversed order
733	///
734	/// # example
735	/// ```
736	/// use faer::mat;
737	/// let matrix = mat![[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]];
738	/// let view = matrix.as_ref();
739	/// let reversed_cols = view.reverse_cols();
740	/// let expected = mat![[3.0, 2.0, 1.0], [6.0, 5.0, 4.0]];
741	/// assert_eq!(expected.as_ref(), reversed_cols);
742	/// ```
743	#[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	/// returns a view over the `self`, with the rows and the columns in
765	/// reversed order
766	///
767	/// # example
768	/// ```
769	/// use faer::mat;
770	/// let matrix = mat![[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]];
771	/// let view = matrix.as_ref();
772	/// let reversed = view.reverse_rows_and_cols();
773	/// let expected = mat![[6.0, 5.0, 4.0], [3.0, 2.0, 1.0]];
774	/// assert_eq!(expected.as_ref(), reversed);
775	/// ```
776	#[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	/// returns a view over the submatrix starting at index `(row_start,
784	/// col_start)`, and with dimensions `(nrows, ncols)`
785	///
786	/// # panics
787	/// the function panics if any of the following conditions are violated:
788	/// * `row_start <= self.nrows()`
789	/// * `col_start <= self.ncols()`
790	/// * `nrows <= self.nrows() - row_start`
791	/// * `ncols <= self.ncols() - col_start`
792	///
793	/// # example
794	/// ```
795	/// use faer::mat;
796	/// let matrix = mat![
797	/// 	[1.0, 5.0, 9.0], //
798	/// 	[2.0, 6.0, 10.0],
799	/// 	[3.0, 7.0, 11.0],
800	/// 	[4.0, 8.0, 12.0f64],
801	/// ];
802	/// let view = matrix.as_ref();
803	/// let submatrix = view.submatrix(
804	/// 	/* row_start: */ 2, /* col_start: */ 1, /* nrows: */ 2,
805	/// 	/* ncols: */ 2,
806	/// );
807	/// let expected = mat![[7.0, 11.0], [8.0, 12.0f64]];
808	/// assert_eq!(expected.as_ref(), submatrix);
809	/// ```
810	#[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	/// returns a view over the submatrix starting at row `row_start`, and with
846	/// number of rows `nrows`
847	///
848	/// # panics
849	/// the function panics if any of the following conditions are violated:
850	/// * `row_start <= self.nrows()`
851	/// * `nrows <= self.nrows() - row_start`
852	///
853	/// # example
854	/// ```
855	/// use faer::mat;
856	/// let matrix = mat![
857	/// 	[1.0, 5.0, 9.0], //
858	/// 	[2.0, 6.0, 10.0],
859	/// 	[3.0, 7.0, 11.0],
860	/// 	[4.0, 8.0, 12.0f64],
861	/// ];
862	/// let view = matrix.as_ref();
863	/// let subrows = view.subrows(/* row_start: */ 1, /* nrows: */ 2);
864	/// let expected = mat![[2.0, 6.0, 10.0], [3.0, 7.0, 11.0],];
865	/// assert_eq!(expected.as_ref(), subrows);
866	/// ```
867	#[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	/// returns a view over the submatrix starting at column `col_start`, and
895	/// with number of columns `ncols`
896	///
897	/// # panics
898	/// the function panics if any of the following conditions are violated:
899	/// * `col_start <= self.ncols()`
900	/// * `ncols <= self.ncols() - col_start`
901	///
902	/// # example
903	/// ```
904	/// use faer::mat;
905	/// let matrix = mat![
906	/// 	[1.0, 5.0, 9.0], //
907	/// 	[2.0, 6.0, 10.0],
908	/// 	[3.0, 7.0, 11.0],
909	/// 	[4.0, 8.0, 12.0f64],
910	/// ];
911	/// let view = matrix.as_ref();
912	/// let subcols = view.subcols(/* col_start: */ 2, /* ncols: */ 1);
913	/// let expected = mat![[9.0], [10.0], [11.0], [12.0f64]];
914	/// assert_eq!(expected.as_ref(), subcols);
915	/// ```
916	#[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	/// returns the input matrix with the given shape after checking that it
944	/// matches the current shape
945	#[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	/// returns the input matrix with the given row shape after checking that it
968	/// matches the current row shape
969	#[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	/// returns the input matrix with the given column shape after checking that
988	/// it matches the current column shape
989	#[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	/// returns the input matrix with dynamic stride
1008	#[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	/// returns the input matrix with dynamic shape
1022	#[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	/// returns the input matrix with dynamic row shape
1036	#[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	/// returns the input matrix with dynamic column shape
1050	#[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	/// returns a view over the row at the given index
1064	///
1065	/// # panics
1066	/// the function panics if any of the following conditions are violated:
1067	/// * `row_idx < self.nrows()`
1068	#[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	/// returns a view over the column at the given index
1082	///
1083	/// # panics
1084	/// the function panics if any of the following conditions are violated:
1085	/// * `col_idx < self.ncols()`
1086	#[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	/// returns an iterator over the columns of the matrix
1100	#[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	/// returns an iterator over the rows of the matrix
1115	#[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	/// returns a parallel iterator over the columns of the matrix
1130	#[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	/// returns a parallel iterator over the rows of the matrix
1154	#[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	/// returns a parallel iterator that provides successive chunks of the
1172	/// columns of this matrix, with each having at most `chunk_size` columns
1173	///
1174	/// if the number of columns is a multiple of `chunk_size`, then all chunks
1175	/// have `chunk_size` columns
1176	///
1177	/// available in every build
1178	#[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	/// returns a parallel iterator that provides exactly `count` successive
1204	/// chunks of the columns of this matrix
1205	///
1206	/// available in every build
1207	#[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	/// returns a parallel iterator that provides successive chunks of the rows
1236	/// of this matrix, with each having at most `chunk_size` rows
1237	///
1238	/// if the number of rows is a multiple of `chunk_size`, then all chunks
1239	/// have `chunk_size` rows
1240	///
1241	/// available in every build
1242	#[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	/// returns a parallel iterator that provides exactly `count` successive
1264	/// chunks of the rows of this matrix
1265	///
1266	/// available in every build
1267	#[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	/// returns a reference to the first row and a view over the remaining ones
1289	/// if the matrix has at least one row, otherwise `None`
1290	#[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	/// returns a reference to the first column and a view over the remaining
1306	/// ones if the matrix has at least one column, otherwise `None`
1307	#[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	/// returns a reference to the last row and a view over the remaining ones
1323	/// if the matrix has at least one row, otherwise `None`
1324	#[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	/// returns a reference to the last column and a view over the remaining
1341	/// ones if the matrix has at least one column, otherwise `None`
1342	#[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	/// returns a view over the matrix with a static column stride equal to
1359	/// `+1`, or `None` otherwise
1360	#[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	/// returns a view over the matrix with a static row stride equal to `+1`,
1446	/// or `None` otherwise
1447	#[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	/// returns references to the element at the given index, or submatrices if
1467	/// either `row` or `col` is a range, with bound checks
1468	///
1469	/// # panics
1470	/// the function panics if any of the following conditions are violated:
1471	/// * `row` must be contained in `[0, self.nrows())`
1472	/// * `col` must be contained in `[0, self.ncols())`
1473	#[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	/// equivalent to `self.get(row, ..)`
1494	#[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	/// equivalent to `self.get(.., col)`
1514	#[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	/// returns references to the element at the given index, or submatrices if
1534	/// either `row` or `col` is a range, without bound checks
1535	///
1536	/// # safety
1537	/// the behavior is undefined if any of the following conditions are
1538	/// violated:
1539	/// * `row` must be contained in `[0, self.nrows())`
1540	/// * `col` must be contained in `[0, self.ncols())`
1541	#[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	/// returns a view over `self`
1581	#[inline]
1582	pub fn as_ref(&self) -> MatRef<'_, T, Rows, Cols, RStride, CStride> {
1583		self.rb()
1584	}
1585
1586	/// returns a newly allocated matrix holding the cloned values of `self`
1587	#[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	/// returns a newly allocated matrix holding the (possibly conjugated)
1606	/// values of `self`
1607	#[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` fills column by column, so for a source whose
1619			// columns are not the contiguous direction every read steps by the
1620			// source's row stride and costs its own cache line -- on `512x512`
1621			// f64 that is 1.01 ms against 0.057, and this is the first thing
1622			// `partial_piv_lu`, `full_piv_lu` and `Qr::new` do with their
1623			// argument. Stage the copy in tiles instead, as the row-major
1624			// factorisations do.
1625			//
1626			// Only an already-canonical source: the tile copy reads the source's
1627			// memory as `T::Canonical`, which is a reinterpretation and not the
1628			// conjugation `Conj::apply` below performs, so a conjugated view (an
1629			// `adjoint().to_owned()`, which the sparse factorisations use) has to
1630			// keep the elementwise path.
1631			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	/// returns the maximum norm of `self`
1657	#[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	/// returns the l2 norm of `self`
1668	#[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	/// returns the squared l2 norm of `self`
1679	#[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	/// returns the l1 norm of `self`
1690	#[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	/// returns the sum of the elements of `self`
1701	#[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	/// returns the determinant of `self`
1717	#[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	/// kronecker product of two matrices
1734	///
1735	/// the kronecker product of two matrices $A$ and $B$ is a block matrix
1736	/// $B$ with the following structure:
1737	///
1738	/// ```text
1739	/// C = [ a[(0, 0)] * B    , a[(0, 1)] * B    , ... , a[(0, n-1)] * B    ]
1740	///     [ a[(1, 0)] * B    , a[(1, 1)] * B    , ... , a[(1, n-1)] * B    ]
1741	///     [ ...              , ...              , ... , ...              ]
1742	///     [ a[(m-1, 0)] * B  , a[(m-1, 1)] * B  , ... , a[(m-1, n-1)] * B  ]
1743	/// ```
1744	///
1745	/// # panics
1746	///
1747	/// panics if `dst` does not have the correct dimensions. the dimensions
1748	/// of `dst` must be `A.nrows() * B.nrows()` by `A.ncols() * B.ncols()`.
1749	///
1750	/// # example
1751	///
1752	/// ```
1753	/// use faer::linalg::kron::kron;
1754	/// use faer::{Mat, mat};
1755	/// let a = mat![[1.0, 2.0], [3.0, 4.0]];
1756	/// let b = mat![[0.0, 5.0], [6.0, 7.0]];
1757	/// let c = mat![
1758	/// 	[0.0, 5.0, 0.0, 10.0],
1759	/// 	[6.0, 7.0, 12.0, 14.0],
1760	/// 	[0.0, 15.0, 0.0, 20.0],
1761	/// 	[18.0, 21.0, 24.0, 28.0],
1762	/// ];
1763	/// let mut dst = Mat::zeros(4, 4);
1764	/// kron(dst.as_mut(), a.as_ref(), b.as_ref());
1765	/// assert_eq!(dst, c);
1766	/// ```
1767	#[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	/// returns `true` if all of the elements of `self` are finite.
1793	/// otherwise returns `false`.
1794	#[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	/// returns `true` if `self` is the identity matrix.
1818	/// otherwise returns `false`.
1819	#[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	/// returns `true` if any of the elements of `self` is `NaN`.
1849	/// otherwise returns `false`.
1850	#[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	/// returns the diagonal of the matrix
1877	#[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	/// Returns the maximum element in the matrix
2030	///
2031	/// # Returns
2032	///
2033	/// * `Option<T>` - The maximum element in the matrix, or `None` if the
2034	///   matrix is empty
2035	///
2036	/// # Examples
2037	///
2038	/// ```
2039	/// use faer::{Mat, mat};
2040	/// let m = mat![[1.0, 5.0, 3.0], [4.0, 2.0, 9.0], [7.0, 8.0, 6.0],];
2041	/// assert_eq!(m.max(), Some(9.0));
2042	/// let empty: Mat<f64> = Mat::new();
2043	/// assert_eq!(empty.max(), None);
2044	/// ```
2045	pub fn max(self) -> Option<T> {
2046		MatRef::internal_max(self.as_dyn())
2047	}
2048
2049	/// Returns the minimum element in the matrix
2050	///
2051	/// # Returns
2052	///
2053	/// * `Option<T>` - The minimum element in the matrix, or `None` if the
2054	///   matrix is empty
2055	///
2056	/// # Examples
2057	///
2058	/// ```
2059	/// use faer::{Mat, mat};
2060	/// let m = mat![[1.0, 5.0, 3.0], [4.0, 2.0, 9.0], [7.0, 8.0, 6.0],];
2061	/// assert_eq!(m.min(), Some(1.0));
2062	/// let empty: Mat<f64> = Mat::new();
2063	/// assert_eq!(empty.min(), None);
2064	/// ```
2065	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	/// Cloning preserves values for column/row-major and general strides.
2124	#[test]
2125	fn test_cloned_from_a_strided_source() {
2126		fn check(m: usize, n: usize, (rs, cs): (isize, isize)) {
2127			// The buffer has to be long enough for the strides the view is
2128			// built with, and the view starts far enough in that a negative
2129			// stride stays inside it.
2130			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}