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	/// only available with the `rayon` feature
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	/// only available with the `rayon` feature
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	/// only available with the `rayon` feature
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	/// only available with the `rayon` feature
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(this.nrows(), this.ncols(), |i, j| {
1619				Conj::apply::<T>(this.at(i, j))
1620			})
1621		}
1622		let this = self.rb();
1623		with_dim!(M, this.nrows().unbound());
1624		with_dim!(N, this.ncols().unbound());
1625		imp(this.as_shape(M, N)).into_shape(this.nrows(), this.ncols())
1626	}
1627
1628	/// returns the maximum norm of `self`
1629	#[inline]
1630	pub fn norm_max(&self) -> Real<T>
1631	where
1632		T: Conjugate,
1633	{
1634		linalg::reductions::norm_max::norm_max(
1635			self.rb().canonical().as_dyn_stride().as_dyn(),
1636		)
1637	}
1638
1639	/// returns the l2 norm of `self`
1640	#[inline]
1641	pub fn norm_l2(&self) -> Real<T>
1642	where
1643		T: Conjugate,
1644	{
1645		linalg::reductions::norm_l2::norm_l2(
1646			self.rb().canonical().as_dyn_stride().as_dyn(),
1647		)
1648	}
1649
1650	/// returns the squared l2 norm of `self`
1651	#[inline]
1652	pub fn squared_norm_l2(&self) -> Real<T>
1653	where
1654		T: Conjugate,
1655	{
1656		linalg::reductions::norm_l2_sqr::norm_l2_sqr(
1657			self.rb().canonical().as_dyn_stride().as_dyn(),
1658		)
1659	}
1660
1661	/// returns the l1 norm of `self`
1662	#[inline]
1663	pub fn norm_l1(&self) -> Real<T>
1664	where
1665		T: Conjugate,
1666	{
1667		linalg::reductions::norm_l1::norm_l1(
1668			self.rb().canonical().as_dyn_stride().as_dyn(),
1669		)
1670	}
1671
1672	/// returns the sum of the elements of `self`
1673	#[inline]
1674	pub fn sum(&self) -> T::Canonical
1675	where
1676		T: Conjugate,
1677	{
1678		let val = linalg::reductions::sum::sum(
1679			self.rb().canonical().as_dyn_stride().as_dyn(),
1680		);
1681		if const { Conj::get::<T>().is_conj() } {
1682			val.conj()
1683		} else {
1684			val
1685		}
1686	}
1687
1688	/// returns the determinant of `self`
1689	#[inline]
1690	pub fn determinant(&self) -> T::Canonical
1691	where
1692		T: Conjugate,
1693	{
1694		let det = linalg::reductions::determinant::determinant(
1695			self.rb().canonical().as_dyn_stride().as_dyn(),
1696		);
1697		if const { T::IS_CANONICAL } {
1698			det
1699		} else {
1700			det.conj()
1701		}
1702	}
1703
1704	/// kronecker product of two matrices
1705	///
1706	/// the kronecker product of two matrices $A$ and $B$ is a block matrix
1707	/// $B$ with the following structure:
1708	///
1709	/// ```text
1710	/// C = [ a[(0, 0)] * B    , a[(0, 1)] * B    , ... , a[(0, n-1)] * B    ]
1711	///     [ a[(1, 0)] * B    , a[(1, 1)] * B    , ... , a[(1, n-1)] * B    ]
1712	///     [ ...              , ...              , ... , ...              ]
1713	///     [ a[(m-1, 0)] * B  , a[(m-1, 1)] * B  , ... , a[(m-1, n-1)] * B  ]
1714	/// ```
1715	///
1716	/// # panics
1717	///
1718	/// panics if `dst` does not have the correct dimensions. the dimensions
1719	/// of `dst` must be `A.nrows() * B.nrows()` by `A.ncols() * B.ncols()`.
1720	///
1721	/// # example
1722	///
1723	/// ```
1724	/// use faer::linalg::kron::kron;
1725	/// use faer::{Mat, mat};
1726	/// let a = mat![[1.0, 2.0], [3.0, 4.0]];
1727	/// let b = mat![[0.0, 5.0], [6.0, 7.0]];
1728	/// let c = mat![
1729	/// 	[0.0, 5.0, 0.0, 10.0],
1730	/// 	[6.0, 7.0, 12.0, 14.0],
1731	/// 	[0.0, 15.0, 0.0, 20.0],
1732	/// 	[18.0, 21.0, 24.0, 28.0],
1733	/// ];
1734	/// let mut dst = Mat::zeros(4, 4);
1735	/// kron(dst.as_mut(), a.as_ref(), b.as_ref());
1736	/// assert_eq!(dst, c);
1737	/// ```
1738	#[inline]
1739	pub fn kron(
1740		&self,
1741		rhs: impl AsMatRef<T: Conjugate<Canonical = T::Canonical>>,
1742	) -> Mat<T::Canonical>
1743	where
1744		T: Conjugate,
1745	{
1746		fn imp<T: ComplexField>(
1747			lhs: MatRef<'_, impl Conjugate<Canonical = T>>,
1748			rhs: MatRef<'_, impl Conjugate<Canonical = T>>,
1749		) -> Mat<T> {
1750			let mut out = Mat::zeros(
1751				lhs.nrows() * rhs.nrows(),
1752				lhs.ncols() * rhs.ncols(),
1753			);
1754			linalg::kron::kron(out.rb_mut(), lhs, rhs);
1755			out
1756		}
1757		imp(
1758			self.rb().as_dyn().as_dyn_stride(),
1759			rhs.as_mat_ref().as_dyn().as_dyn_stride(),
1760		)
1761	}
1762
1763	/// returns `true` if all of the elements of `self` are finite.
1764	/// otherwise returns `false`.
1765	#[inline]
1766	pub fn is_all_finite(&self) -> bool
1767	where
1768		T: Conjugate,
1769	{
1770		fn imp<T: ComplexField>(A: MatRef<'_, T>) -> bool {
1771			with_dim!({
1772				let M = A.nrows();
1773				let N = A.ncols();
1774			});
1775			let A = A.as_shape(M, N);
1776			for j in N.indices() {
1777				for i in M.indices() {
1778					if !A[(i, j)].is_finite() {
1779						return false;
1780					}
1781				}
1782			}
1783			true
1784		}
1785		imp(self.rb().as_dyn().as_dyn_stride().canonical())
1786	}
1787
1788	/// returns `true` if `self` is the identity matrix.
1789	/// otherwise returns `false`.
1790	#[inline]
1791	pub fn is_identity(&self) -> bool
1792	where
1793		T: Conjugate,
1794	{
1795		fn imp<T: ComplexField>(A: MatRef<'_, T>) -> bool {
1796			with_dim!({
1797				let M = A.nrows();
1798				let N = A.ncols();
1799			});
1800			let A = A.as_shape(M, N);
1801			for j in N.indices() {
1802				for i in M.indices() {
1803					if *i == *j {
1804						if A[(i, j)] != one() {
1805							return false;
1806						}
1807					} else {
1808						if A[(i, j)] != zero() {
1809							return false;
1810						}
1811					}
1812				}
1813			}
1814			true
1815		}
1816		imp(self.rb().as_dyn().as_dyn_stride().canonical())
1817	}
1818
1819	/// returns `true` if any of the elements of `self` is `NaN`.
1820	/// otherwise returns `false`.
1821	#[inline]
1822	pub fn has_nan(&self) -> bool
1823	where
1824		T: Conjugate,
1825	{
1826		fn imp<T: ComplexField>(A: MatRef<'_, T>) -> bool {
1827			with_dim!({
1828				let M = A.nrows();
1829				let N = A.ncols();
1830			});
1831			let A = A.as_shape(M, N);
1832			for j in N.indices() {
1833				for i in M.indices() {
1834					if A[(i, j)].is_nan() {
1835						return true;
1836					}
1837				}
1838			}
1839			false
1840		}
1841		imp(self.rb().as_dyn().as_dyn_stride().canonical())
1842	}
1843}
1844impl<'a, T, Dim: Shape, RStride: Stride, CStride: Stride>
1845	MatRef<'a, T, Dim, Dim, RStride, CStride>
1846{
1847	/// returns the diagonal of the matrix
1848	#[inline]
1849	pub fn diagonal(self) -> DiagRef<'a, T, Dim, isize> {
1850		let k = Ord::min(self.nrows(), self.ncols());
1851		DiagRef {
1852			0: crate::diag::Ref {
1853				inner: unsafe {
1854					ColRef::from_raw_parts(
1855						self.as_ptr(),
1856						k,
1857						self.row_stride().element_stride()
1858							+ self.col_stride().element_stride(),
1859					)
1860				},
1861			},
1862		}
1863	}
1864}
1865impl<'ROWS, 'COLS, 'a, T, RStride: Stride, CStride: Stride>
1866	MatRef<'a, T, Dim<'ROWS>, Dim<'COLS>, RStride, CStride>
1867{
1868	#[doc(hidden)]
1869	#[inline]
1870	pub fn split_with<'TOP, 'BOT, 'LEFT, 'RIGHT>(
1871		self,
1872		row: Partition<'TOP, 'BOT, 'ROWS>,
1873		col: Partition<'LEFT, 'RIGHT, 'COLS>,
1874	) -> (
1875		MatRef<'a, T, Dim<'TOP>, Dim<'LEFT>, RStride, CStride>,
1876		MatRef<'a, T, Dim<'TOP>, Dim<'RIGHT>, RStride, CStride>,
1877		MatRef<'a, T, Dim<'BOT>, Dim<'LEFT>, RStride, CStride>,
1878		MatRef<'a, T, Dim<'BOT>, Dim<'RIGHT>, RStride, CStride>,
1879	) {
1880		let (a, b, c, d) = self.split_at(row.midpoint(), col.midpoint());
1881		(
1882			a.as_shape(row.head, col.head),
1883			b.as_shape(row.head, col.tail),
1884			c.as_shape(row.tail, col.head),
1885			d.as_shape(row.tail, col.tail),
1886		)
1887	}
1888}
1889impl<'ROWS, 'a, T, Cols: Shape, RStride: Stride, CStride: Stride>
1890	MatRef<'a, T, Dim<'ROWS>, Cols, RStride, CStride>
1891{
1892	#[doc(hidden)]
1893	#[inline]
1894	pub fn split_rows_with<'TOP, 'BOT>(
1895		self,
1896		row: Partition<'TOP, 'BOT, 'ROWS>,
1897	) -> (
1898		MatRef<'a, T, Dim<'TOP>, Cols, RStride, CStride>,
1899		MatRef<'a, T, Dim<'BOT>, Cols, RStride, CStride>,
1900	) {
1901		let (a, b) = self.split_at_row(row.midpoint());
1902		(a.as_row_shape(row.head), b.as_row_shape(row.tail))
1903	}
1904}
1905impl<'COLS, 'a, T, Rows: Shape, RStride: Stride, CStride: Stride>
1906	MatRef<'a, T, Rows, Dim<'COLS>, RStride, CStride>
1907{
1908	#[doc(hidden)]
1909	#[inline]
1910	pub fn split_cols_with<'LEFT, 'RIGHT>(
1911		self,
1912		col: Partition<'LEFT, 'RIGHT, 'COLS>,
1913	) -> (
1914		MatRef<'a, T, Rows, Dim<'LEFT>, RStride, CStride>,
1915		MatRef<'a, T, Rows, Dim<'RIGHT>, RStride, CStride>,
1916	) {
1917		let (a, b) = self.split_at_col(col.midpoint());
1918		(a.as_col_shape(col.head), b.as_col_shape(col.tail))
1919	}
1920}
1921impl<
1922	'a,
1923	T: core::fmt::Debug,
1924	Rows: Shape,
1925	Cols: Shape,
1926	RStride: Stride,
1927	CStride: Stride,
1928> core::fmt::Debug for Ref<'a, T, Rows, Cols, RStride, CStride>
1929{
1930	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1931		fn imp<'M, 'N, T: core::fmt::Debug>(
1932			this: MatRef<'_, T, Dim<'M>, Dim<'N>>,
1933			f: &mut core::fmt::Formatter<'_>,
1934		) -> core::fmt::Result {
1935			writeln!(f, "[")?;
1936			for i in this.nrows().indices() {
1937				this.row(i).fmt(f)?;
1938				f.write_str(",\n")?;
1939			}
1940			write!(f, "]")
1941		}
1942		let this = generic::Mat::from_inner_ref(self);
1943		with_dim!(M, this.nrows().unbound());
1944		with_dim!(N, this.ncols().unbound());
1945		imp(this.as_shape(M, N).as_dyn_stride(), f)
1946	}
1947}
1948impl<'a, T: RealField> MatRef<'a, T, usize, usize> {
1949	pub(crate) fn internal_max(self) -> Option<T> {
1950		if self.nrows().unbound() == 0 || self.ncols().unbound() == 0 {
1951			return None;
1952		}
1953		let mut max_val = self.get(0, 0);
1954		let this = if self.row_stride().unsigned_abs() == 1 {
1955			self.transpose()
1956		} else {
1957			self
1958		};
1959		let this = if this.col_stride() > 0 {
1960			this
1961		} else {
1962			this.reverse_cols()
1963		};
1964		this.row_iter().for_each(|row| {
1965			row.iter().for_each(|val| {
1966				if val > max_val {
1967					max_val = &val;
1968				}
1969			});
1970		});
1971		Some((*max_val).clone())
1972	}
1973
1974	pub(crate) fn internal_min(self) -> Option<T> {
1975		if self.nrows().unbound() == 0 || self.ncols().unbound() == 0 {
1976			return None;
1977		}
1978		let mut min_val = self.get(0, 0);
1979		let this = if self.row_stride().unsigned_abs() == 1 {
1980			self.transpose()
1981		} else {
1982			self
1983		};
1984		let this = if this.col_stride() > 0 {
1985			this
1986		} else {
1987			this.reverse_cols()
1988		};
1989		this.row_iter().for_each(|row| {
1990			row.iter().for_each(|val| {
1991				if val < min_val {
1992					min_val = &val;
1993				}
1994			});
1995		});
1996		Some((*min_val).clone())
1997	}
1998}
1999impl<'a, T: RealField, Rows: Shape, Cols: Shape> MatRef<'a, T, Rows, Cols> {
2000	/// Returns the maximum element in the matrix
2001	///
2002	/// # Returns
2003	///
2004	/// * `Option<T>` - The maximum element in the matrix, or `None` if the
2005	///   matrix is empty
2006	///
2007	/// # Examples
2008	///
2009	/// ```
2010	/// use faer::{Mat, mat};
2011	/// let m = mat![[1.0, 5.0, 3.0], [4.0, 2.0, 9.0], [7.0, 8.0, 6.0],];
2012	/// assert_eq!(m.max(), Some(9.0));
2013	/// let empty: Mat<f64> = Mat::new();
2014	/// assert_eq!(empty.max(), None);
2015	/// ```
2016	pub fn max(self) -> Option<T> {
2017		MatRef::internal_max(self.as_dyn())
2018	}
2019
2020	/// Returns the minimum element in the matrix
2021	///
2022	/// # Returns
2023	///
2024	/// * `Option<T>` - The minimum element in the matrix, or `None` if the
2025	///   matrix is empty
2026	///
2027	/// # Examples
2028	///
2029	/// ```
2030	/// use faer::{Mat, mat};
2031	/// let m = mat![[1.0, 5.0, 3.0], [4.0, 2.0, 9.0], [7.0, 8.0, 6.0],];
2032	/// assert_eq!(m.min(), Some(1.0));
2033	/// let empty: Mat<f64> = Mat::new();
2034	/// assert_eq!(empty.min(), None);
2035	/// ```
2036	pub fn min(self) -> Option<T> {
2037		MatRef::internal_min(self.as_dyn())
2038	}
2039}
2040#[cfg(test)]
2041mod tests {
2042	use super::*;
2043	#[test]
2044	fn test_min() {
2045		let m = mat![[1.0, 5.0, 3.0], [4.0, 2.0, 9.0], [7.0, 8.0, 6.0],];
2046		assert_eq!(m.as_ref().min(), Some(1.0));
2047		let empty: Mat<f64> = Mat::new();
2048		assert_eq!(empty.as_ref().min(), None);
2049	}
2050	#[test]
2051	fn test_max() {
2052		let m = mat![[1.0, 5.0, 3.0], [4.0, 2.0, 9.0], [7.0, 8.0, 6.0],];
2053		assert_eq!(m.as_ref().max(), Some(9.0));
2054		let empty: Mat<f64> = Mat::new();
2055		assert_eq!(empty.as_ref().max(), None);
2056	}
2057}