Skip to main content

faer/mat/
matmut.rs

1use super::{MatRef, *};
2use crate::internal_prelude::*;
3use crate::utils::bound::{Dim, Partition};
4use crate::{Conj, ContiguousFwd, Idx, IdxInc};
5
6use equator::assert;
7use faer_traits::ComplexField;
8use generativity::Guard;
9use linalg::zip::Last;
10/// see [`super::MatMut`]
11pub struct Mut<
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 mut T>,
21}
22#[repr(transparent)]
23pub(crate) struct SyncCell<T>(T);
24unsafe impl<T> Sync for SyncCell<T> {}
25impl<'short, T, Rows: Copy, Cols: Copy, RStride: Copy, CStride: Copy>
26	Reborrow<'short> for Mut<'_, T, Rows, Cols, RStride, CStride>
27{
28	type Target = Ref<'short, T, Rows, Cols, RStride, CStride>;
29
30	#[inline]
31	fn rb(&'short self) -> Self::Target {
32		Ref {
33			imp: self.imp,
34			__marker: PhantomData,
35		}
36	}
37}
38impl<'short, T, Rows: Copy, Cols: Copy, RStride: Copy, CStride: Copy>
39	ReborrowMut<'short> for Mut<'_, T, Rows, Cols, RStride, CStride>
40{
41	type Target = Mut<'short, T, Rows, Cols, RStride, CStride>;
42
43	#[inline]
44	fn rb_mut(&'short mut self) -> Self::Target {
45		Mut {
46			imp: self.imp,
47			__marker: PhantomData,
48		}
49	}
50}
51impl<'a, T, Rows: Copy, Cols: Copy, RStride: Copy, CStride: Copy> IntoConst
52	for Mut<'a, T, Rows, Cols, RStride, CStride>
53{
54	type Target = Ref<'a, T, Rows, Cols, RStride, CStride>;
55
56	#[inline]
57	fn into_const(self) -> Self::Target {
58		Ref {
59			imp: self.imp,
60			__marker: PhantomData,
61		}
62	}
63}
64unsafe impl<T: Sync, Rows: Sync, Cols: Sync, RStride: Sync, CStride: Sync> Sync
65	for Mut<'_, T, Rows, Cols, RStride, CStride>
66{
67}
68unsafe impl<T: Send, Rows: Send, Cols: Send, RStride: Send, CStride: Send> Send
69	for Mut<'_, T, Rows, Cols, RStride, CStride>
70{
71}
72impl<'a, T> MatMut<'a, T> {
73	/// equivalent to
74	/// `MatMut::from_row_major_slice_mut(array.as_flattened_mut(), ROWS, COLS)`
75	#[inline]
76	pub fn from_row_major_array_mut<const ROWS: usize, const COLS: usize>(
77		array: &'a mut [[T; COLS]; ROWS],
78	) -> Self {
79		unsafe {
80			Self::from_raw_parts_mut(
81				array as *mut _ as *mut T,
82				ROWS,
83				COLS,
84				COLS as isize,
85				1,
86			)
87		}
88	}
89
90	/// equivalent to
91	/// `MatMut::from_column_major_slice_mut(array.as_flattened_mut(), ROWS,
92	/// COLS)`
93	#[inline]
94	pub fn from_column_major_array_mut<const ROWS: usize, const COLS: usize>(
95		array: &'a mut [[T; ROWS]; COLS],
96	) -> Self {
97		unsafe {
98			Self::from_raw_parts_mut(
99				array as *mut _ as *mut T,
100				ROWS,
101				COLS,
102				1,
103				ROWS as isize,
104			)
105		}
106	}
107}
108impl<'a, T, Rows: Shape, Cols: Shape, RStride: Stride, CStride: Stride>
109	MatMut<'a, T, Rows, Cols, RStride, CStride>
110{
111	/// creates a `MatMut` from a pointer to the matrix data, dimensions, and
112	/// strides
113	///
114	/// the row (resp. column) stride is the offset from the memory address of a
115	/// given matrix element at index `(row: i, col: j)`, to the memory address
116	/// of the matrix element at index `(row: i + 1, col: 0)` (resp. `(row: 0,
117	/// col: i + 1)`). this offset is specified in number of elements, not in
118	/// bytes
119	///
120	/// # safety
121	/// the behavior is undefined if any of the following conditions are
122	/// violated:
123	/// * for each matrix unit, the entire memory region addressed by the matrix
124	///   must be contained
125	/// within a single allocation, accessible in its entirety by the
126	/// corresponding pointer in `ptr`
127	/// * for each matrix unit, the corresponding pointer must be non null and
128	///   properly aligned,
129	/// even for a zero-sized matrix.
130	/// * the values accessible by the matrix must be initialized at some point
131	///   before they are read, or
132	/// references to them are formed
133	/// * no aliasing (including self aliasing) is allowed. in other words, none
134	///   of the elements
135	/// accessible by any matrix unit may be accessed for reads or writes by any
136	/// other means for the duration of the lifetime `'a`. no two elements
137	/// within a single matrix unit may point to the same address (such a thing
138	/// can be achieved with a zero stride, for example), and no two
139	/// matrix units may point to the same address
140	///
141	/// # example
142	///
143	/// ```
144	/// use faer::{MatMut, mat};
145	/// // row major matrix with 2 rows, 3 columns, with a column at the end that we want to skip.
146	/// // the row stride is the pointer offset from the address of 1.0 to the address of 4.0,
147	/// // which is 4
148	/// // the column stride is the pointer offset from the address of 1.0 to the address of 2.0,
149	/// // which is 1
150	/// let mut data = [[1.0, 2.0, 3.0, f64::NAN], [4.0, 5.0, 6.0, f64::NAN]];
151	/// let mut matrix =
152	/// 	unsafe { MatMut::from_raw_parts_mut(data.as_mut_ptr() as *mut f64, 2, 3, 4, 1) };
153	/// let expected = mat![[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]];
154	/// assert_eq!(expected.as_ref(), matrix);
155	/// ```
156	#[inline]
157	#[track_caller]
158	pub const unsafe fn from_raw_parts_mut(
159		ptr: *mut T,
160		nrows: Rows,
161		ncols: Cols,
162		row_stride: RStride,
163		col_stride: CStride,
164	) -> Self {
165		MatMut {
166			0: Mut {
167				imp: MatView {
168					ptr: NonNull::new_unchecked(ptr),
169					nrows,
170					ncols,
171					row_stride,
172					col_stride,
173				},
174				__marker: PhantomData,
175			},
176		}
177	}
178
179	/// returns a pointer to the matrix data
180	#[inline]
181	pub fn as_ptr(&self) -> *const T {
182		self.imp.ptr.as_ptr()
183	}
184
185	/// returns the number of rows of the matrix
186	#[inline]
187	pub fn nrows(&self) -> Rows {
188		self.imp.nrows
189	}
190
191	/// returns the number of columns of the matrix
192	#[inline]
193	pub fn ncols(&self) -> Cols {
194		self.imp.ncols
195	}
196
197	/// returns the number of rows and columns of the matrix
198	#[inline]
199	pub fn shape(&self) -> (Rows, Cols) {
200		(self.nrows(), self.ncols())
201	}
202
203	/// returns the row stride of the matrix, specified in number of elements,
204	/// not in bytes
205	#[inline]
206	pub fn row_stride(&self) -> RStride {
207		self.imp.row_stride
208	}
209
210	/// returns the column stride of the matrix, specified in number of
211	/// elements, not in bytes
212	#[inline]
213	pub fn col_stride(&self) -> CStride {
214		self.imp.col_stride
215	}
216
217	#[inline]
218	pub fn map<U>(&self, f: impl Fn(&T) -> U) -> Mat<U, Rows, Cols> {
219		self.rb().map(f)
220	}
221
222	#[inline]
223	pub fn for_each(&self, f: impl Fn(&T)) {
224		self.rb().for_each(f)
225	}
226
227	#[inline]
228	pub fn map_mut<U>(
229		&mut self,
230		f: impl FnMut(&mut T) -> U,
231	) -> Mat<U, Rows, Cols> {
232		let mut f = f;
233		zip!(self).map(|unzip!(x)| f(x))
234	}
235
236	#[inline]
237	pub fn for_each_mut(&mut self, f: impl FnMut(&mut T)) {
238		let mut f = f;
239		zip!(self).for_each(|unzip!(x)| f(x))
240	}
241
242	/// returns a raw pointer to the element at the given index
243	#[inline]
244	pub fn ptr_at(&self, row: IdxInc<Rows>, col: IdxInc<Cols>) -> *const T {
245		self.rb().ptr_at(row, col)
246	}
247
248	/// returns a raw pointer to the element at the given index, assuming the
249	/// provided index is within the matrix bounds
250	///
251	/// # safety
252	/// the behavior is undefined if any of the following conditions are
253	/// violated:
254	/// * `row < self.nrows()`
255	/// * `col < self.ncols()`
256	#[inline]
257	#[track_caller]
258	pub unsafe fn ptr_inbounds_at(
259		&self,
260		row: Idx<Rows>,
261		col: Idx<Cols>,
262	) -> *const T {
263		self.rb().ptr_inbounds_at(row, col)
264	}
265
266	#[inline]
267	#[track_caller]
268	/// see [`MatRef::split_at`]
269	pub fn split_at(
270		self,
271		row: IdxInc<Rows>,
272		col: IdxInc<Cols>,
273	) -> (
274		MatRef<'a, T, usize, usize, RStride, CStride>,
275		MatRef<'a, T, usize, usize, RStride, CStride>,
276		MatRef<'a, T, usize, usize, RStride, CStride>,
277		MatRef<'a, T, usize, usize, RStride, CStride>,
278	) {
279		self.into_const().split_at(row, col)
280	}
281
282	#[inline]
283	#[track_caller]
284	/// see [`MatRef::split_at_row`]
285	pub fn split_at_row(
286		self,
287		row: IdxInc<Rows>,
288	) -> (
289		MatRef<'a, T, usize, Cols, RStride, CStride>,
290		MatRef<'a, T, usize, Cols, RStride, CStride>,
291	) {
292		self.into_const().split_at_row(row)
293	}
294
295	#[inline]
296	#[track_caller]
297	/// see [`MatRef::split_at_col`]
298	pub fn split_at_col(
299		self,
300		col: IdxInc<Cols>,
301	) -> (
302		MatRef<'a, T, Rows, usize, RStride, CStride>,
303		MatRef<'a, T, Rows, usize, RStride, CStride>,
304	) {
305		self.into_const().split_at_col(col)
306	}
307
308	#[inline]
309	/// see [`MatRef::transpose`]
310	pub fn transpose(self) -> MatRef<'a, T, Cols, Rows, CStride, RStride> {
311		MatRef {
312			0: Ref {
313				imp: MatView {
314					ptr: self.imp.ptr,
315					nrows: self.imp.ncols,
316					ncols: self.imp.nrows,
317					row_stride: self.imp.col_stride,
318					col_stride: self.imp.row_stride,
319				},
320				__marker: PhantomData,
321			},
322		}
323	}
324
325	#[inline]
326	/// see [`MatRef::conjugate`]
327	pub fn conjugate(self) -> MatRef<'a, T::Conj, Rows, Cols, RStride, CStride>
328	where
329		T: Conjugate,
330	{
331		self.into_const().conjugate()
332	}
333
334	#[inline]
335	/// see [`MatRef::canonical`]
336	pub fn canonical(
337		self,
338	) -> MatRef<'a, T::Canonical, Rows, Cols, RStride, CStride>
339	where
340		T: Conjugate,
341	{
342		self.into_const().canonical()
343	}
344
345	#[inline]
346	/// see [`MatRef::adjoint`]
347	pub fn adjoint(self) -> MatRef<'a, T::Conj, Cols, Rows, CStride, RStride>
348	where
349		T: Conjugate,
350	{
351		self.into_const().adjoint()
352	}
353
354	#[inline]
355	/// see [`MatRef::reverse_rows`]
356	pub fn reverse_rows(
357		self,
358	) -> MatRef<'a, T, Rows, Cols, RStride::Rev, CStride> {
359		self.into_const().reverse_rows()
360	}
361
362	#[inline]
363	/// see [`MatRef::reverse_cols`]
364	pub fn reverse_cols(
365		self,
366	) -> MatRef<'a, T, Rows, Cols, RStride, CStride::Rev> {
367		self.into_const().reverse_cols()
368	}
369
370	#[inline]
371	/// see [`MatRef::reverse_rows_and_cols`]
372	pub fn reverse_rows_and_cols(
373		self,
374	) -> MatRef<'a, T, Rows, Cols, RStride::Rev, CStride::Rev> {
375		self.into_const().reverse_rows_and_cols()
376	}
377
378	#[inline]
379	#[track_caller]
380	/// see [`MatRef::submatrix`]
381	pub fn submatrix<V: Shape, H: Shape>(
382		self,
383		row_start: IdxInc<Rows>,
384		col_start: IdxInc<Cols>,
385		nrows: V,
386		ncols: H,
387	) -> MatRef<'a, T, V, H, RStride, CStride> {
388		self.into_const()
389			.submatrix(row_start, col_start, nrows, ncols)
390	}
391
392	#[inline]
393	#[track_caller]
394	/// see [`MatRef::subrows`]
395	pub fn subrows<V: Shape>(
396		self,
397		row_start: IdxInc<Rows>,
398		nrows: V,
399	) -> MatRef<'a, T, V, Cols, RStride, CStride> {
400		self.into_const().subrows(row_start, nrows)
401	}
402
403	#[inline]
404	#[track_caller]
405	/// see [`MatRef::subcols`]
406	pub fn subcols<H: Shape>(
407		self,
408		col_start: IdxInc<Cols>,
409		ncols: H,
410	) -> MatRef<'a, T, Rows, H, RStride, CStride> {
411		self.into_const().subcols(col_start, ncols)
412	}
413
414	#[inline]
415	#[track_caller]
416	/// see [`MatRef::as_shape`]
417	pub fn as_shape<V: Shape, H: Shape>(
418		self,
419		nrows: V,
420		ncols: H,
421	) -> MatRef<'a, T, V, H, RStride, CStride> {
422		self.into_const().as_shape(nrows, ncols)
423	}
424
425	#[inline]
426	#[track_caller]
427	/// see [`MatRef::as_row_shape`]
428	pub fn as_row_shape<V: Shape>(
429		self,
430		nrows: V,
431	) -> MatRef<'a, T, V, Cols, RStride, CStride> {
432		self.into_const().as_row_shape(nrows)
433	}
434
435	#[inline]
436	#[track_caller]
437	/// see [`MatRef::as_col_shape`]
438	pub fn as_col_shape<H: Shape>(
439		self,
440		ncols: H,
441	) -> MatRef<'a, T, Rows, H, RStride, CStride> {
442		self.into_const().as_col_shape(ncols)
443	}
444
445	#[inline]
446	/// see [`MatRef::as_dyn_stride`]
447	pub fn as_dyn_stride(self) -> MatRef<'a, T, Rows, Cols, isize, isize> {
448		self.into_const().as_dyn_stride()
449	}
450
451	#[inline]
452	/// see [`MatRef::as_dyn`]
453	pub fn as_dyn(self) -> MatRef<'a, T, usize, usize, RStride, CStride> {
454		self.into_const().as_dyn()
455	}
456
457	#[inline]
458	/// see [`MatRef::as_dyn_rows`]
459	pub fn as_dyn_rows(self) -> MatRef<'a, T, usize, Cols, RStride, CStride> {
460		self.into_const().as_dyn_rows()
461	}
462
463	#[inline]
464	/// see [`MatRef::as_dyn_cols`]
465	pub fn as_dyn_cols(self) -> MatRef<'a, T, Rows, usize, RStride, CStride> {
466		self.into_const().as_dyn_cols()
467	}
468
469	#[inline]
470	#[track_caller]
471	/// see [`MatRef::row`]
472	pub fn row(self, i: Idx<Rows>) -> RowRef<'a, T, Cols, CStride> {
473		self.into_const().row(i)
474	}
475
476	#[inline]
477	#[track_caller]
478	/// see [`MatRef::col`]
479	pub fn col(self, j: Idx<Cols>) -> ColRef<'a, T, Rows, RStride> {
480		self.into_const().col(j)
481	}
482
483	#[inline]
484	/// see [`MatRef::col_iter`]
485	pub fn col_iter(
486		self,
487	) -> impl 'a
488	+ ExactSizeIterator
489	+ DoubleEndedIterator<Item = ColRef<'a, T, Rows, RStride>>
490	where
491		Rows: 'a,
492		Cols: 'a,
493	{
494		self.into_const().col_iter()
495	}
496
497	#[inline]
498	/// see [`MatRef::row_iter`]
499	pub fn row_iter(
500		self,
501	) -> impl 'a
502	+ ExactSizeIterator
503	+ DoubleEndedIterator<Item = RowRef<'a, T, Cols, CStride>>
504	where
505		Rows: 'a,
506		Cols: 'a,
507	{
508		self.into_const().row_iter()
509	}
510
511	#[inline]
512	#[cfg(feature = "rayon")]
513	/// see [`MatRef::par_col_iter`]
514	pub fn par_col_iter(
515		self,
516	) -> impl 'a
517	+ rayon::iter::IndexedParallelIterator<
518		Item = ColRef<'a, T, Rows, RStride>,
519	>
520	where
521		T: Sync,
522		Rows: 'a,
523		Cols: 'a,
524	{
525		self.into_const().par_col_iter()
526	}
527
528	#[inline]
529	#[cfg(feature = "rayon")]
530	/// see [`MatRef::par_row_iter`]
531	pub fn par_row_iter(
532		self,
533	) -> impl 'a
534	+ rayon::iter::IndexedParallelIterator<
535		Item = RowRef<'a, T, Cols, CStride>,
536	>
537	where
538		T: Sync,
539		Rows: 'a,
540		Cols: 'a,
541	{
542		self.into_const().par_row_iter()
543	}
544
545	#[inline]
546	#[track_caller]
547	#[cfg(feature = "rayon")]
548	/// see [`MatRef::par_col_chunks`]
549	pub fn par_col_chunks(
550		self,
551		chunk_size: usize,
552	) -> impl 'a
553	+ rayon::iter::IndexedParallelIterator<
554		Item = MatRef<'a, T, Rows, usize, RStride, CStride>,
555	>
556	where
557		T: Sync,
558		Rows: 'a,
559		Cols: 'a,
560	{
561		self.into_const().par_col_chunks(chunk_size)
562	}
563
564	#[inline]
565	#[track_caller]
566	#[cfg(feature = "rayon")]
567	/// see [`MatRef::par_col_partition`]
568	pub fn par_col_partition(
569		self,
570		count: usize,
571	) -> impl 'a
572	+ rayon::iter::IndexedParallelIterator<
573		Item = MatRef<'a, T, Rows, usize, RStride, CStride>,
574	>
575	where
576		T: Sync,
577		Rows: 'a,
578		Cols: 'a,
579	{
580		self.into_const().par_col_partition(count)
581	}
582
583	#[inline]
584	#[track_caller]
585	#[cfg(feature = "rayon")]
586	/// see [`MatRef::par_row_chunks`]
587	pub fn par_row_chunks(
588		self,
589		chunk_size: usize,
590	) -> impl 'a
591	+ rayon::iter::IndexedParallelIterator<
592		Item = MatRef<'a, T, usize, Cols, RStride, CStride>,
593	>
594	where
595		T: Sync,
596		Rows: 'a,
597		Cols: 'a,
598	{
599		self.into_const().par_row_chunks(chunk_size)
600	}
601
602	#[inline]
603	#[track_caller]
604	#[cfg(feature = "rayon")]
605	/// see [`MatRef::par_row_partition`]
606	pub fn par_row_partition(
607		self,
608		count: usize,
609	) -> impl 'a
610	+ rayon::iter::IndexedParallelIterator<
611		Item = MatRef<'a, T, usize, Cols, RStride, CStride>,
612	>
613	where
614		T: Sync,
615		Rows: 'a,
616		Cols: 'a,
617	{
618		self.into_const().par_row_partition(count)
619	}
620
621	#[inline]
622	/// see [`MatRef::try_as_col_major`]
623	pub fn try_as_col_major(
624		self,
625	) -> Option<MatRef<'a, T, Rows, Cols, ContiguousFwd, CStride>> {
626		self.into_const().try_as_col_major()
627	}
628
629	#[inline]
630	/// see [`MatRef::try_as_row_major`]
631	pub fn try_as_row_major(
632		self,
633	) -> Option<MatRef<'a, T, Rows, Cols, RStride, ContiguousFwd>> {
634		self.into_const().try_as_row_major()
635	}
636
637	#[doc(hidden)]
638	#[inline]
639	pub unsafe fn const_cast(
640		self,
641	) -> MatMut<'a, T, Rows, Cols, RStride, CStride> {
642		self
643	}
644
645	/// see [`MatRef::)]`]	#[doc(hidden)]
646	#[inline]
647	pub fn bind<'M, 'N>(
648		self,
649		row: Guard<'M>,
650		col: Guard<'N>,
651	) -> MatMut<'a, T, Dim<'M>, Dim<'N>, RStride, CStride> {
652		unsafe {
653			MatMut::from_raw_parts_mut(
654				self.as_ptr_mut(),
655				self.nrows().bind(row),
656				self.ncols().bind(col),
657				self.row_stride(),
658				self.col_stride(),
659			)
660		}
661	}
662
663	#[doc(hidden)]
664	#[inline]
665	pub fn bind_r<'M>(
666		self,
667		row: Guard<'M>,
668	) -> MatMut<'a, T, Dim<'M>, Cols, RStride, CStride> {
669		unsafe {
670			MatMut::from_raw_parts_mut(
671				self.as_ptr_mut(),
672				self.nrows().bind(row),
673				self.ncols(),
674				self.row_stride(),
675				self.col_stride(),
676			)
677		}
678	}
679
680	#[doc(hidden)]
681	#[inline]
682	pub fn bind_c<'N>(
683		self,
684		col: Guard<'N>,
685	) -> MatMut<'a, T, Rows, Dim<'N>, RStride, CStride> {
686		unsafe {
687			MatMut::from_raw_parts_mut(
688				self.as_ptr_mut(),
689				self.nrows(),
690				self.ncols().bind(col),
691				self.row_stride(),
692				self.col_stride(),
693			)
694		}
695	}
696
697	#[track_caller]
698	#[inline]
699	/// see [`MatRef::get`]
700	pub fn get<RowRange, ColRange>(
701		self,
702		row: RowRange,
703		col: ColRange,
704	) -> <MatRef<'a, T, Rows, Cols, RStride, CStride> as MatIndex<
705		RowRange,
706		ColRange,
707	>>::Target
708	where
709		MatRef<'a, T, Rows, Cols, RStride, CStride>:
710			MatIndex<RowRange, ColRange>,
711	{
712		<MatRef<'a, T, Rows, Cols, RStride, CStride> as MatIndex<
713			RowRange,
714			ColRange,
715		>>::get(self.into_const(), row, col)
716	}
717
718	#[track_caller]
719	#[inline]
720	/// see [`MatRef::get_unchecked`]
721	///
722	/// # safety
723	/// same as [`MatRef::get_unchecked`]
724	pub unsafe fn get_unchecked<RowRange, ColRange>(
725		self,
726		row: RowRange,
727		col: ColRange,
728	) -> <MatRef<'a, T, Rows, Cols, RStride, CStride> as MatIndex<
729		RowRange,
730		ColRange,
731	>>::Target
732	where
733		MatRef<'a, T, Rows, Cols, RStride, CStride>:
734			MatIndex<RowRange, ColRange>,
735	{
736		unsafe {
737			<MatRef<'a, T, Rows, Cols, RStride, CStride> as MatIndex<
738				RowRange,
739				ColRange,
740			>>::get_unchecked(self.into_const(), row, col)
741		}
742	}
743
744	/// see [`MatRef::get`]
745	#[track_caller]
746	#[inline]
747	pub fn get_mut<RowRange, ColRange>(
748		self,
749		row: RowRange,
750		col: ColRange,
751	) -> <MatMut<'a, T, Rows, Cols, RStride, CStride> as MatIndex<
752		RowRange,
753		ColRange,
754	>>::Target
755	where
756		MatMut<'a, T, Rows, Cols, RStride, CStride>:
757			MatIndex<RowRange, ColRange>,
758	{
759		<MatMut<'a, T, Rows, Cols, RStride, CStride> as MatIndex<
760			RowRange,
761			ColRange,
762		>>::get(self, row, col)
763	}
764
765	/// see [`MatRef::get_unchecked`]
766	///
767	/// # safety
768	/// same as [`MatRef::get_unchecked`]
769	#[track_caller]
770	#[inline]
771	pub unsafe fn get_mut_unchecked<RowRange, ColRange>(
772		self,
773		row: RowRange,
774		col: ColRange,
775	) -> <MatMut<'a, T, Rows, Cols, RStride, CStride> as MatIndex<
776		RowRange,
777		ColRange,
778	>>::Target
779	where
780		MatMut<'a, T, Rows, Cols, RStride, CStride>:
781			MatIndex<RowRange, ColRange>,
782	{
783		unsafe {
784			<MatMut<'a, T, Rows, Cols, RStride, CStride> as MatIndex<
785				RowRange,
786				ColRange,
787			>>::get_unchecked(self, row, col)
788		}
789	}
790}
791impl<
792	T,
793	Rows: Shape,
794	Cols: Shape,
795	RStride: Stride,
796	CStride: Stride,
797	Inner: for<'short> ReborrowMut<
798			'short,
799			Target = Mut<'short, T, Rows, Cols, RStride, CStride>,
800		>,
801> generic::Mat<Inner>
802{
803	/// returns a view over `self`
804	#[inline]
805	pub fn as_mut(&mut self) -> MatMut<'_, T, Rows, Cols, RStride, CStride> {
806		self.rb_mut()
807	}
808
809	/// copies the lower triangular half of `other`, including the diagonal,
810	/// into `self`
811	#[inline]
812	#[track_caller]
813	pub fn copy_from_triangular_lower<RhsT: Conjugate<Canonical = T>>(
814		&mut self,
815		other: impl AsMatRef<T = RhsT, Rows = Rows, Cols = Cols>,
816	) where
817		T: ComplexField,
818	{
819		let other = other.as_mat_ref();
820		let mut this = self.rb_mut();
821		assert!(all(
822			this.nrows() == other.nrows(),
823			this.ncols() == other.ncols(),
824		));
825		let (m, n) = this.shape();
826		make_guard!(M);
827		make_guard!(N);
828		let M = m.bind(M);
829		let N = n.bind(N);
830		let this = this.rb_mut().as_shape_mut(M, N).as_dyn_stride_mut();
831		let other = other.as_shape(M, N);
832		imp(this, other.canonical(), Conj::get::<RhsT>());
833		pub fn imp<'M, 'N, T: ComplexField>(
834			this: MatMut<'_, T, Dim<'M>, Dim<'N>>,
835			other: MatRef<'_, T, Dim<'M>, Dim<'N>>,
836			conj_: Conj,
837		) {
838			match conj_ {
839				Conj::No => {
840					zip!(this, other).for_each_triangular_lower(
841						crate::linalg::zip::Diag::Include,
842						|unzip!(dst, src)| *dst = src.copy(),
843					);
844				},
845				Conj::Yes => {
846					zip!(this, other).for_each_triangular_lower(
847						crate::linalg::zip::Diag::Include,
848						|unzip!(dst, src)| *dst = src.conj(),
849					);
850				},
851			}
852		}
853	}
854
855	/// copies the upper triangular half of `other`, including the diagonal,
856	/// into `self`
857	#[inline]
858	#[track_caller]
859	pub fn copy_from_triangular_upper<RhsT: Conjugate<Canonical = T>>(
860		&mut self,
861		other: impl AsMatRef<T = RhsT, Rows = Rows, Cols = Cols>,
862	) where
863		T: ComplexField,
864	{
865		(*self)
866			.rb_mut()
867			.transpose_mut()
868			.copy_from_triangular_lower(other.as_mat_ref().transpose())
869	}
870
871	/// copies `other` into `self`
872	#[inline]
873	#[track_caller]
874	pub fn copy_from<RhsT: Conjugate<Canonical = T>>(
875		&mut self,
876		other: impl AsMatRef<T = RhsT, Rows = Rows, Cols = Cols>,
877	) where
878		T: ComplexField,
879	{
880		let other = other.as_mat_ref();
881		let mut this = self.rb_mut();
882		assert!(all(
883			this.nrows() == other.nrows(),
884			this.ncols() == other.ncols(),
885		));
886		let (m, n) = this.shape();
887		make_guard!(M);
888		make_guard!(N);
889		let M = m.bind(M);
890		let N = n.bind(N);
891		let this = this.rb_mut().as_shape_mut(M, N).as_dyn_stride_mut();
892		let other = other.as_shape(M, N);
893		imp(this, other.canonical(), Conj::get::<RhsT>());
894		pub fn imp<'M, 'N, T: ComplexField>(
895			this: MatMut<'_, T, Dim<'M>, Dim<'N>>,
896			other: MatRef<'_, T, Dim<'M>, Dim<'N>>,
897			conj_: Conj,
898		) {
899			match conj_ {
900				Conj::No => {
901					zip!(this, other)
902						.for_each(|unzip!(dst, src)| *dst = src.copy());
903				},
904				Conj::Yes => {
905					zip!(this, other)
906						.for_each(|unzip!(dst, src)| *dst = src.conj());
907				},
908			}
909		}
910	}
911
912	/// copies the lower triangular half of `other`, excluding the diagonal,
913	/// into `self`
914	#[inline]
915	#[track_caller]
916	pub fn copy_from_strict_triangular_lower<RhsT: Conjugate<Canonical = T>>(
917		&mut self,
918		other: impl AsMatRef<T = RhsT, Rows = Rows, Cols = Cols>,
919	) where
920		T: ComplexField,
921	{
922		let other = other.as_mat_ref();
923		let mut this = self.rb_mut();
924		assert!(all(
925			this.nrows() == other.nrows(),
926			this.ncols() == other.ncols(),
927		));
928		let (m, n) = this.shape();
929		make_guard!(M);
930		make_guard!(N);
931		let M = m.bind(M);
932		let N = n.bind(N);
933		let this = this.rb_mut().as_shape_mut(M, N).as_dyn_stride_mut();
934		let other = other.as_shape(M, N);
935		imp(this, other.canonical(), Conj::get::<RhsT>());
936		pub fn imp<'M, 'N, T: ComplexField>(
937			this: MatMut<'_, T, Dim<'M>, Dim<'N>>,
938			other: MatRef<'_, T, Dim<'M>, Dim<'N>>,
939			conj_: Conj,
940		) {
941			match conj_ {
942				Conj::No => {
943					zip!(this, other).for_each_triangular_lower(
944						crate::linalg::zip::Diag::Skip,
945						|unzip!(dst, src)| *dst = src.copy(),
946					);
947				},
948				Conj::Yes => {
949					zip!(this, other).for_each_triangular_lower(
950						crate::linalg::zip::Diag::Skip,
951						|unzip!(dst, src)| *dst = src.conj(),
952					);
953				},
954			}
955		}
956	}
957
958	/// copies the upper triangular half of `other`, excluding the diagonal,
959	/// into `self`
960	#[inline]
961	#[track_caller]
962	pub fn copy_from_strict_triangular_upper<RhsT: Conjugate<Canonical = T>>(
963		&mut self,
964		other: impl AsMatRef<T = RhsT, Rows = Rows, Cols = Cols>,
965	) where
966		T: ComplexField,
967	{
968		(*self)
969			.rb_mut()
970			.transpose_mut()
971			.copy_from_strict_triangular_lower(other.as_mat_ref().transpose())
972	}
973
974	/// fills all the elements of `self` with `value`
975	#[inline]
976	pub fn fill(&mut self, value: T)
977	where
978		T: Clone,
979	{
980		fn cloner<T: Clone>(value: T) -> impl for<'a> FnMut(Last<&'a mut T>) {
981			#[inline]
982			move |x| *x.0 = value.clone()
983		}
984		z!(self.rb_mut().as_dyn_mut()).for_each(cloner::<T>(value));
985	}
986}
987impl<'a, T, Rows: Shape, Cols: Shape, RStride: Stride, CStride: Stride>
988	MatMut<'a, T, Rows, Cols, RStride, CStride>
989{
990	#[inline]
991	/// see [`MatRef::as_ptr`]
992	pub fn as_ptr_mut(&self) -> *mut T {
993		self.imp.ptr.as_ptr()
994	}
995
996	#[inline]
997	/// see [`MatRef::ptr_at`]
998	pub fn ptr_at_mut(&self, row: IdxInc<Rows>, col: IdxInc<Cols>) -> *mut T {
999		self.rb().ptr_at(row, col) as *mut T
1000	}
1001
1002	#[inline]
1003	#[track_caller]
1004	/// see [`MatRef::ptr_inbounds_at`]
1005	pub unsafe fn ptr_inbounds_at_mut(
1006		&self,
1007		row: Idx<Rows>,
1008		col: Idx<Cols>,
1009	) -> *mut T {
1010		self.rb().ptr_inbounds_at(row, col) as *mut T
1011	}
1012
1013	#[inline]
1014	#[track_caller]
1015	/// see [`MatRef::split_at`]
1016	pub fn split_at_mut(
1017		self,
1018		row: IdxInc<Rows>,
1019		col: IdxInc<Cols>,
1020	) -> (
1021		MatMut<'a, T, usize, usize, RStride, CStride>,
1022		MatMut<'a, T, usize, usize, RStride, CStride>,
1023		MatMut<'a, T, usize, usize, RStride, CStride>,
1024		MatMut<'a, T, usize, usize, RStride, CStride>,
1025	) {
1026		let (a, b, c, d) = self.into_const().split_at(row, col);
1027		unsafe {
1028			(
1029				a.const_cast(),
1030				b.const_cast(),
1031				c.const_cast(),
1032				d.const_cast(),
1033			)
1034		}
1035	}
1036
1037	#[inline]
1038	#[track_caller]
1039	/// see [`MatRef::split_at_row`]
1040	pub fn split_at_row_mut(
1041		self,
1042		row: IdxInc<Rows>,
1043	) -> (
1044		MatMut<'a, T, usize, Cols, RStride, CStride>,
1045		MatMut<'a, T, usize, Cols, RStride, CStride>,
1046	) {
1047		let (a, b) = self.into_const().split_at_row(row);
1048		unsafe { (a.const_cast(), b.const_cast()) }
1049	}
1050
1051	#[inline]
1052	#[track_caller]
1053	/// see [`MatRef::split_at_col`]
1054	pub fn split_at_col_mut(
1055		self,
1056		col: IdxInc<Cols>,
1057	) -> (
1058		MatMut<'a, T, Rows, usize, RStride, CStride>,
1059		MatMut<'a, T, Rows, usize, RStride, CStride>,
1060	) {
1061		let (a, b) = self.into_const().split_at_col(col);
1062		unsafe { (a.const_cast(), b.const_cast()) }
1063	}
1064
1065	#[inline]
1066	/// see [`MatRef::transpose`]
1067	pub fn transpose_mut(self) -> MatMut<'a, T, Cols, Rows, CStride, RStride> {
1068		MatMut {
1069			0: Mut {
1070				imp: MatView {
1071					ptr: self.imp.ptr,
1072					nrows: self.imp.ncols,
1073					ncols: self.imp.nrows,
1074					row_stride: self.imp.col_stride,
1075					col_stride: self.imp.row_stride,
1076				},
1077				__marker: PhantomData,
1078			},
1079		}
1080	}
1081
1082	#[inline]
1083	/// see [`MatRef::conjugate`]
1084	pub fn conjugate_mut(
1085		self,
1086	) -> MatMut<'a, T::Conj, Rows, Cols, RStride, CStride>
1087	where
1088		T: Conjugate,
1089	{
1090		unsafe { self.into_const().conjugate().const_cast() }
1091	}
1092
1093	#[inline]
1094	/// see [`MatRef::canonical`]
1095	pub fn canonical_mut(
1096		self,
1097	) -> MatMut<'a, T::Canonical, Rows, Cols, RStride, CStride>
1098	where
1099		T: Conjugate,
1100	{
1101		unsafe { self.into_const().canonical().const_cast() }
1102	}
1103
1104	#[inline]
1105	/// see [`MatRef::adjoint`]
1106	pub fn adjoint_mut(
1107		self,
1108	) -> MatMut<'a, T::Conj, Cols, Rows, CStride, RStride>
1109	where
1110		T: Conjugate,
1111	{
1112		unsafe { self.into_const().adjoint().const_cast() }
1113	}
1114
1115	#[inline]
1116	#[track_caller]
1117	pub(crate) fn at_mut(self, row: Idx<Rows>, col: Idx<Cols>) -> &'a mut T {
1118		assert!(all(row < self.nrows(), col < self.ncols()));
1119		unsafe { self.at_mut_unchecked(row, col) }
1120	}
1121
1122	#[inline]
1123	#[track_caller]
1124	pub(crate) unsafe fn at_mut_unchecked(
1125		self,
1126		row: Idx<Rows>,
1127		col: Idx<Cols>,
1128	) -> &'a mut T {
1129		&mut *self.ptr_inbounds_at_mut(row, col)
1130	}
1131
1132	#[inline]
1133	/// see [`MatRef::reverse_rows`]
1134	pub fn reverse_rows_mut(
1135		self,
1136	) -> MatMut<'a, T, Rows, Cols, RStride::Rev, CStride> {
1137		unsafe { self.into_const().reverse_rows().const_cast() }
1138	}
1139
1140	#[inline]
1141	/// see [`MatRef::reverse_cols`]
1142	pub fn reverse_cols_mut(
1143		self,
1144	) -> MatMut<'a, T, Rows, Cols, RStride, CStride::Rev> {
1145		unsafe { self.into_const().reverse_cols().const_cast() }
1146	}
1147
1148	#[inline]
1149	/// see [`MatRef::reverse_rows_and_cols`]
1150	pub fn reverse_rows_and_cols_mut(
1151		self,
1152	) -> MatMut<'a, T, Rows, Cols, RStride::Rev, CStride::Rev> {
1153		unsafe { self.into_const().reverse_rows_and_cols().const_cast() }
1154	}
1155
1156	#[inline]
1157	#[track_caller]
1158	/// see [`MatRef::submatrix`]
1159	pub fn submatrix_mut<V: Shape, H: Shape>(
1160		self,
1161		row_start: IdxInc<Rows>,
1162		col_start: IdxInc<Cols>,
1163		nrows: V,
1164		ncols: H,
1165	) -> MatMut<'a, T, V, H, RStride, CStride> {
1166		unsafe {
1167			self.into_const()
1168				.submatrix(row_start, col_start, nrows, ncols)
1169				.const_cast()
1170		}
1171	}
1172
1173	#[inline]
1174	#[track_caller]
1175	/// see [`MatRef::subrows`]
1176	pub fn subrows_mut<V: Shape>(
1177		self,
1178		row_start: IdxInc<Rows>,
1179		nrows: V,
1180	) -> MatMut<'a, T, V, Cols, RStride, CStride> {
1181		unsafe { self.into_const().subrows(row_start, nrows).const_cast() }
1182	}
1183
1184	#[inline]
1185	#[track_caller]
1186	/// see [`MatRef::subcols`]
1187	pub fn subcols_mut<H: Shape>(
1188		self,
1189		col_start: IdxInc<Cols>,
1190		ncols: H,
1191	) -> MatMut<'a, T, Rows, H, RStride, CStride> {
1192		unsafe { self.into_const().subcols(col_start, ncols).const_cast() }
1193	}
1194
1195	#[inline]
1196	#[track_caller]
1197	/// see [`MatRef::as_shape`]
1198	pub fn as_shape_mut<V: Shape, H: Shape>(
1199		self,
1200		nrows: V,
1201		ncols: H,
1202	) -> MatMut<'a, T, V, H, RStride, CStride> {
1203		unsafe { self.into_const().as_shape(nrows, ncols).const_cast() }
1204	}
1205
1206	#[inline]
1207	#[track_caller]
1208	/// see [`MatRef::as_row_shape`]
1209	pub fn as_row_shape_mut<V: Shape>(
1210		self,
1211		nrows: V,
1212	) -> MatMut<'a, T, V, Cols, RStride, CStride> {
1213		unsafe { self.into_const().as_row_shape(nrows).const_cast() }
1214	}
1215
1216	#[inline]
1217	#[track_caller]
1218	/// see [`MatRef::as_col_shape`]
1219	pub fn as_col_shape_mut<H: Shape>(
1220		self,
1221		ncols: H,
1222	) -> MatMut<'a, T, Rows, H, RStride, CStride> {
1223		unsafe { self.into_const().as_col_shape(ncols).const_cast() }
1224	}
1225
1226	#[inline]
1227	/// see [`MatRef::as_dyn_stride`]
1228	pub fn as_dyn_stride_mut(self) -> MatMut<'a, T, Rows, Cols, isize, isize> {
1229		unsafe { self.into_const().as_dyn_stride().const_cast() }
1230	}
1231
1232	#[inline]
1233	/// see [`MatRef::as_dyn`]
1234	pub fn as_dyn_mut(self) -> MatMut<'a, T, usize, usize, RStride, CStride> {
1235		unsafe { self.into_const().as_dyn().const_cast() }
1236	}
1237
1238	#[inline]
1239	/// see [`MatRef::as_dyn_rows`]
1240	pub fn as_dyn_rows_mut(
1241		self,
1242	) -> MatMut<'a, T, usize, Cols, RStride, CStride> {
1243		unsafe { self.into_const().as_dyn_rows().const_cast() }
1244	}
1245
1246	#[inline]
1247	/// see [`MatRef::as_dyn_cols`]
1248	pub fn as_dyn_cols_mut(
1249		self,
1250	) -> MatMut<'a, T, Rows, usize, RStride, CStride> {
1251		unsafe { self.into_const().as_dyn_cols().const_cast() }
1252	}
1253
1254	#[inline]
1255	#[track_caller]
1256	/// see [`MatRef::row`]
1257	pub fn row_mut(self, i: Idx<Rows>) -> RowMut<'a, T, Cols, CStride> {
1258		unsafe { self.into_const().row(i).const_cast() }
1259	}
1260
1261	#[inline]
1262	#[track_caller]
1263	/// see [`MatRef::col`]
1264	pub fn col_mut(self, j: Idx<Cols>) -> ColMut<'a, T, Rows, RStride> {
1265		unsafe { self.into_const().col(j).const_cast() }
1266	}
1267
1268	#[inline]
1269	/// see [`MatRef::col_iter`]
1270	pub fn col_iter_mut(
1271		self,
1272	) -> impl 'a
1273	+ ExactSizeIterator
1274	+ DoubleEndedIterator<Item = ColMut<'a, T, Rows, RStride>>
1275	where
1276		Rows: 'a,
1277		Cols: 'a,
1278	{
1279		self.into_const()
1280			.col_iter()
1281			.map(|x| unsafe { x.const_cast() })
1282	}
1283
1284	#[inline]
1285	/// see [`MatRef::row_iter`]
1286	pub fn row_iter_mut(
1287		self,
1288	) -> impl 'a
1289	+ ExactSizeIterator
1290	+ DoubleEndedIterator<Item = RowMut<'a, T, Cols, CStride>>
1291	where
1292		Rows: 'a,
1293		Cols: 'a,
1294	{
1295		self.into_const()
1296			.row_iter()
1297			.map(|x| unsafe { x.const_cast() })
1298	}
1299
1300	#[inline]
1301	pub(crate) unsafe fn as_type<U>(
1302		self,
1303	) -> MatMut<'a, U, Rows, Cols, RStride, CStride> {
1304		MatMut::from_raw_parts_mut(
1305			self.as_ptr_mut() as *mut U,
1306			self.nrows(),
1307			self.ncols(),
1308			self.row_stride(),
1309			self.col_stride(),
1310		)
1311	}
1312
1313	#[inline]
1314	#[cfg(feature = "rayon")]
1315	/// see [`MatRef::par_col_iter`]
1316	pub fn par_col_iter_mut(
1317		self,
1318	) -> impl 'a
1319	+ rayon::iter::IndexedParallelIterator<
1320		Item = ColMut<'a, T, Rows, RStride>,
1321	>
1322	where
1323		T: Send,
1324		Rows: 'a,
1325		Cols: 'a,
1326	{
1327		use rayon::prelude::*;
1328		unsafe {
1329			self.as_type::<SyncCell<T>>()
1330				.into_const()
1331				.par_col_iter()
1332				.map(|x| x.const_cast())
1333				.map(|x| x.as_type())
1334		}
1335	}
1336
1337	#[inline]
1338	#[cfg(feature = "rayon")]
1339	/// see [`MatRef::par_row_iter`]
1340	pub fn par_row_iter_mut(
1341		self,
1342	) -> impl 'a
1343	+ rayon::iter::IndexedParallelIterator<
1344		Item = RowMut<'a, T, Cols, CStride>,
1345	>
1346	where
1347		T: Send,
1348		Rows: 'a,
1349		Cols: 'a,
1350	{
1351		use rayon::prelude::*;
1352		unsafe {
1353			self.as_type::<SyncCell<T>>()
1354				.into_const()
1355				.par_row_iter()
1356				.map(|x| x.const_cast())
1357				.map(|x| x.as_type())
1358		}
1359	}
1360
1361	#[inline]
1362	#[track_caller]
1363	#[cfg(feature = "rayon")]
1364	/// see [`MatRef::par_col_chunks`]
1365	pub fn par_col_chunks_mut(
1366		self,
1367		chunk_size: usize,
1368	) -> impl 'a
1369	+ rayon::iter::IndexedParallelIterator<
1370		Item = MatMut<'a, T, Rows, usize, RStride, CStride>,
1371	>
1372	where
1373		T: Send,
1374		Rows: 'a,
1375		Cols: 'a,
1376	{
1377		use rayon::prelude::*;
1378		unsafe {
1379			self.as_type::<SyncCell<T>>()
1380				.into_const()
1381				.par_col_chunks(chunk_size)
1382				.map(|x| x.const_cast())
1383				.map(|x| x.as_type())
1384		}
1385	}
1386
1387	#[inline]
1388	#[track_caller]
1389	#[cfg(feature = "rayon")]
1390	/// see [`MatRef::par_col_partition`]
1391	pub fn par_col_partition_mut(
1392		self,
1393		count: usize,
1394	) -> impl 'a
1395	+ rayon::iter::IndexedParallelIterator<
1396		Item = MatMut<'a, T, Rows, usize, RStride, CStride>,
1397	>
1398	where
1399		T: Send,
1400		Rows: 'a,
1401		Cols: 'a,
1402	{
1403		use rayon::prelude::*;
1404		unsafe {
1405			self.as_type::<SyncCell<T>>()
1406				.into_const()
1407				.par_col_partition(count)
1408				.map(|x| x.const_cast())
1409				.map(|x| x.as_type())
1410		}
1411	}
1412
1413	#[inline]
1414	#[track_caller]
1415	#[cfg(feature = "rayon")]
1416	/// see [`MatRef::par_row_chunks`]
1417	pub fn par_row_chunks_mut(
1418		self,
1419		chunk_size: usize,
1420	) -> impl 'a
1421	+ rayon::iter::IndexedParallelIterator<
1422		Item = MatMut<'a, T, usize, Cols, RStride, CStride>,
1423	>
1424	where
1425		T: Send,
1426		Rows: 'a,
1427		Cols: 'a,
1428	{
1429		use rayon::prelude::*;
1430		unsafe {
1431			self.as_type::<SyncCell<T>>()
1432				.into_const()
1433				.par_row_chunks(chunk_size)
1434				.map(|x| x.const_cast())
1435				.map(|x| x.as_type())
1436		}
1437	}
1438
1439	#[inline]
1440	#[track_caller]
1441	#[cfg(feature = "rayon")]
1442	/// see [`MatRef::par_row_partition`]
1443	pub fn par_row_partition_mut(
1444		self,
1445		count: usize,
1446	) -> impl 'a
1447	+ rayon::iter::IndexedParallelIterator<
1448		Item = MatMut<'a, T, usize, Cols, RStride, CStride>,
1449	>
1450	where
1451		T: Send,
1452		Rows: 'a,
1453		Cols: 'a,
1454	{
1455		use rayon::prelude::*;
1456		unsafe {
1457			self.as_type::<SyncCell<T>>()
1458				.into_const()
1459				.par_row_partition(count)
1460				.map(|x| x.const_cast())
1461				.map(|x| x.as_type())
1462		}
1463	}
1464
1465	#[inline]
1466	/// see [`MatRef::split_first_row`]
1467	pub fn split_first_row_mut(
1468		self,
1469	) -> Option<(
1470		RowMut<'a, T, Cols, CStride>,
1471		MatMut<'a, T, usize, Cols, RStride, CStride>,
1472	)> {
1473		if let Some(i0) = self.nrows().idx_inc(1) {
1474			let (head, tail) = self.split_at_row_mut(i0);
1475			Some((head.row_mut(0), tail))
1476		} else {
1477			None
1478		}
1479	}
1480
1481	#[inline]
1482	/// see [`MatRef::split_first_col`]
1483	pub fn split_first_col_mut(
1484		self,
1485	) -> Option<(
1486		ColMut<'a, T, Rows, RStride>,
1487		MatMut<'a, T, Rows, usize, RStride, CStride>,
1488	)> {
1489		if let Some(i0) = self.ncols().idx_inc(1) {
1490			let (head, tail) = self.split_at_col_mut(i0);
1491			Some((head.col_mut(0), tail))
1492		} else {
1493			None
1494		}
1495	}
1496
1497	#[inline]
1498	/// see [`MatRef::split_last_row`]
1499	pub fn split_last_row_mut(
1500		self,
1501	) -> Option<(
1502		RowMut<'a, T, Cols, CStride>,
1503		MatMut<'a, T, usize, Cols, RStride, CStride>,
1504	)> {
1505		if self.nrows().unbound() > 0 {
1506			let i0 = self.nrows().checked_idx_inc(self.nrows().unbound() - 1);
1507			let (head, tail) = self.split_at_row_mut(i0);
1508			Some((tail.row_mut(0), head))
1509		} else {
1510			None
1511		}
1512	}
1513
1514	#[inline]
1515	/// see [`MatRef::split_last_col`]
1516	pub fn split_last_col_mut(
1517		self,
1518	) -> Option<(
1519		ColMut<'a, T, Rows, RStride>,
1520		MatMut<'a, T, Rows, usize, RStride, CStride>,
1521	)> {
1522		if self.ncols().unbound() > 0 {
1523			let i0 = self.ncols().checked_idx_inc(self.ncols().unbound() - 1);
1524			let (head, tail) = self.split_at_col_mut(i0);
1525			Some((tail.col_mut(0), head))
1526		} else {
1527			None
1528		}
1529	}
1530
1531	#[inline]
1532	/// see [`MatRef::split_first_row`]
1533	pub fn split_first_row(
1534		self,
1535	) -> Option<(
1536		RowRef<'a, T, Cols, CStride>,
1537		MatRef<'a, T, usize, Cols, RStride, CStride>,
1538	)> {
1539		self.into_const().split_first_row()
1540	}
1541
1542	#[inline]
1543	/// see [`MatRef::split_first_col`]
1544	pub fn split_first_col(
1545		self,
1546	) -> Option<(
1547		ColRef<'a, T, Rows, RStride>,
1548		MatRef<'a, T, Rows, usize, RStride, CStride>,
1549	)> {
1550		self.into_const().split_first_col()
1551	}
1552
1553	#[inline]
1554	/// see [`MatRef::split_last_row`]
1555	pub fn split_last_row(
1556		self,
1557	) -> Option<(
1558		RowRef<'a, T, Cols, CStride>,
1559		MatRef<'a, T, usize, Cols, RStride, CStride>,
1560	)> {
1561		self.into_const().split_last_row()
1562	}
1563
1564	#[inline]
1565	/// see [`MatRef::split_last_col`]
1566	pub fn split_last_col(
1567		self,
1568	) -> Option<(
1569		ColRef<'a, T, Rows, RStride>,
1570		MatRef<'a, T, Rows, usize, RStride, CStride>,
1571	)> {
1572		self.into_const().split_last_col()
1573	}
1574
1575	#[inline]
1576	/// see [`MatRef::try_as_col_major`]
1577	pub fn try_as_col_major_mut(
1578		self,
1579	) -> Option<MatMut<'a, T, Rows, Cols, ContiguousFwd, CStride>> {
1580		self.into_const()
1581			.try_as_col_major()
1582			.map(|x| unsafe { x.const_cast() })
1583	}
1584
1585	#[inline]
1586	/// see [`MatRef::try_as_row_major`]
1587	pub fn try_as_row_major_mut(
1588		self,
1589	) -> Option<MatMut<'a, T, Rows, Cols, RStride, ContiguousFwd>> {
1590		self.into_const()
1591			.try_as_row_major()
1592			.map(|x| unsafe { x.const_cast() })
1593	}
1594
1595	/// returns two views over the given columns
1596	///
1597	/// # panics
1598	/// panics if `i0 == i1`
1599	#[inline]
1600	#[track_caller]
1601	pub fn two_cols_mut(
1602		self,
1603		i0: Idx<Cols>,
1604		i1: Idx<Cols>,
1605	) -> (ColMut<'a, T, Rows, RStride>, ColMut<'a, T, Rows, RStride>) {
1606		assert!(i0 != i1);
1607		let this = self.into_const();
1608		unsafe { (this.col(i0).const_cast(), this.col(i1).const_cast()) }
1609	}
1610
1611	/// returns two views over the given rows
1612	///
1613	/// # panics
1614	/// panics if `i0 == i1`
1615	#[inline]
1616	#[track_caller]
1617	pub fn two_rows_mut(
1618		self,
1619		i0: Idx<Rows>,
1620		i1: Idx<Rows>,
1621	) -> (RowMut<'a, T, Cols, CStride>, RowMut<'a, T, Cols, CStride>) {
1622		assert!(i0 != i1);
1623		let this = self.into_const();
1624		unsafe { (this.row(i0).const_cast(), this.row(i1).const_cast()) }
1625	}
1626
1627	#[inline]
1628	pub(crate) fn __at_mut(self, (i, j): (Idx<Rows>, Idx<Cols>)) -> &'a mut T {
1629		self.at_mut(i, j)
1630	}
1631}
1632impl<'a, T, Rows: Shape, Cols: Shape> MatMut<'a, T, Rows, Cols> {
1633	/// creates a `MatMut` from slice views over the matrix data, and the matrix
1634	/// dimensions. the data is interpreted in a column-major format, so that
1635	/// the first chunk of `nrows` values from the slices goes in the first
1636	/// column of the matrix, the second chunk of `nrows` values goes in the
1637	/// second column, and so on
1638	///
1639	/// # panics
1640	/// the function panics if any of the following conditions are violated:
1641	/// * `nrows * ncols == slice.len()`
1642	///
1643	/// # example
1644	/// ```
1645	/// use faer::{MatMut, mat};
1646	/// let mut slice = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0_f64];
1647	/// let view = MatMut::from_column_major_slice_mut(&mut slice, 3, 2);
1648	/// let expected = mat![[1.0, 4.0], [2.0, 5.0], [3.0, 6.0]];
1649	/// assert_eq!(expected, view);
1650	/// ```
1651	#[inline]
1652	#[track_caller]
1653	pub fn from_column_major_slice_mut(
1654		slice: &'a mut [T],
1655		nrows: Rows,
1656		ncols: Cols,
1657	) -> Self
1658	where
1659		T: Sized,
1660	{
1661		from_slice_assert(nrows.unbound(), ncols.unbound(), slice.len());
1662		unsafe {
1663			Self::from_raw_parts_mut(
1664				slice.as_mut_ptr(),
1665				nrows,
1666				ncols,
1667				1,
1668				nrows.unbound() as isize,
1669			)
1670		}
1671	}
1672
1673	/// creates a `MatMut` from slice views over the matrix data, and the matrix
1674	/// dimensions. the data is interpreted in a column-major format, where the
1675	/// beginnings of two consecutive columns are separated by `col_stride`
1676	/// elements.
1677	#[inline]
1678	#[track_caller]
1679	pub fn from_column_major_slice_with_stride_mut(
1680		slice: &'a mut [T],
1681		nrows: Rows,
1682		ncols: Cols,
1683		col_stride: usize,
1684	) -> Self
1685	where
1686		T: Sized,
1687	{
1688		from_strided_column_major_slice_mut_assert(
1689			nrows.unbound(),
1690			ncols.unbound(),
1691			col_stride,
1692			slice.len(),
1693		);
1694		unsafe {
1695			Self::from_raw_parts_mut(
1696				slice.as_mut_ptr(),
1697				nrows,
1698				ncols,
1699				1,
1700				col_stride as isize,
1701			)
1702		}
1703	}
1704
1705	/// creates a `MatMut` from slice views over the matrix data, and the matrix
1706	/// dimensions. the data is interpreted in a row-major format, so that the
1707	/// first chunk of `ncols` values from the slices goes in the first column
1708	/// of the matrix, the second chunk of `ncols` values goes in the second
1709	/// column, and so on
1710	///
1711	/// # panics
1712	/// the function panics if any of the following conditions are violated:
1713	/// * `nrows * ncols == slice.len()`
1714	///
1715	/// # example
1716	/// ```
1717	/// use faer::{MatMut, mat};
1718	/// let mut slice = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0_f64];
1719	/// let view = MatMut::from_row_major_slice_mut(&mut slice, 3, 2);
1720	/// let expected = mat![[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]];
1721	/// assert_eq!(expected, view);
1722	/// ```
1723	#[inline]
1724	#[track_caller]
1725	pub fn from_row_major_slice_mut(
1726		slice: &'a mut [T],
1727		nrows: Rows,
1728		ncols: Cols,
1729	) -> Self
1730	where
1731		T: Sized,
1732	{
1733		MatMut::from_column_major_slice_mut(slice, ncols, nrows).transpose_mut()
1734	}
1735
1736	/// creates a `MatMut` from slice views over the matrix data, and the matrix
1737	/// dimensions. the data is interpreted in a row-major format, where the
1738	/// beginnings of two consecutive rows are separated by `row_stride`
1739	/// elements.
1740	#[inline]
1741	#[track_caller]
1742	pub fn from_row_major_slice_with_stride_mut(
1743		slice: &'a mut [T],
1744		nrows: Rows,
1745		ncols: Cols,
1746		row_stride: usize,
1747	) -> Self
1748	where
1749		T: Sized,
1750	{
1751		from_strided_row_major_slice_mut_assert(
1752			nrows.unbound(),
1753			ncols.unbound(),
1754			row_stride,
1755			slice.len(),
1756		);
1757		unsafe {
1758			Self::from_raw_parts_mut(
1759				slice.as_mut_ptr(),
1760				nrows,
1761				ncols,
1762				1,
1763				row_stride as isize,
1764			)
1765		}
1766	}
1767}
1768impl<'ROWS, 'COLS, 'a, T, RStride: Stride, CStride: Stride>
1769	MatMut<'a, T, Dim<'ROWS>, Dim<'COLS>, RStride, CStride>
1770{
1771	#[doc(hidden)]
1772	#[inline]
1773	pub fn split_with_mut<'TOP, 'BOT, 'LEFT, 'RIGHT>(
1774		self,
1775		row: Partition<'TOP, 'BOT, 'ROWS>,
1776		col: Partition<'LEFT, 'RIGHT, 'COLS>,
1777	) -> (
1778		MatMut<'a, T, Dim<'TOP>, Dim<'LEFT>, RStride, CStride>,
1779		MatMut<'a, T, Dim<'TOP>, Dim<'RIGHT>, RStride, CStride>,
1780		MatMut<'a, T, Dim<'BOT>, Dim<'LEFT>, RStride, CStride>,
1781		MatMut<'a, T, Dim<'BOT>, Dim<'RIGHT>, RStride, CStride>,
1782	) {
1783		let (a, b, c, d) = self.split_at_mut(row.midpoint(), col.midpoint());
1784		(
1785			a.as_shape_mut(row.head, col.head),
1786			b.as_shape_mut(row.head, col.tail),
1787			c.as_shape_mut(row.tail, col.head),
1788			d.as_shape_mut(row.tail, col.tail),
1789		)
1790	}
1791}
1792impl<'ROWS, 'a, T, Cols: Shape, RStride: Stride, CStride: Stride>
1793	MatMut<'a, T, Dim<'ROWS>, Cols, RStride, CStride>
1794{
1795	#[doc(hidden)]
1796	#[inline]
1797	pub fn split_rows_with_mut<'TOP, 'BOT>(
1798		self,
1799		row: Partition<'TOP, 'BOT, 'ROWS>,
1800	) -> (
1801		MatMut<'a, T, Dim<'TOP>, Cols, RStride, CStride>,
1802		MatMut<'a, T, Dim<'BOT>, Cols, RStride, CStride>,
1803	) {
1804		let (a, b) = self.split_at_row_mut(row.midpoint());
1805		(a.as_row_shape_mut(row.head), b.as_row_shape_mut(row.tail))
1806	}
1807}
1808impl<'COLS, 'a, T, Rows: Shape, RStride: Stride, CStride: Stride>
1809	MatMut<'a, T, Rows, Dim<'COLS>, RStride, CStride>
1810{
1811	#[doc(hidden)]
1812	#[inline]
1813	pub fn split_cols_with_mut<'LEFT, 'RIGHT>(
1814		self,
1815		col: Partition<'LEFT, 'RIGHT, 'COLS>,
1816	) -> (
1817		MatMut<'a, T, Rows, Dim<'LEFT>, RStride, CStride>,
1818		MatMut<'a, T, Rows, Dim<'RIGHT>, RStride, CStride>,
1819	) {
1820		let (a, b) = self.split_at_col_mut(col.midpoint());
1821		(a.as_col_shape_mut(col.head), b.as_col_shape_mut(col.tail))
1822	}
1823}
1824impl<'ROWS, 'COLS, 'a, T, RStride: Stride, CStride: Stride>
1825	MatMut<'a, T, Dim<'ROWS>, Dim<'COLS>, RStride, CStride>
1826{
1827	#[doc(hidden)]
1828	#[inline]
1829	pub fn split_with<'TOP, 'BOT, 'LEFT, 'RIGHT>(
1830		self,
1831		row: Partition<'TOP, 'BOT, 'ROWS>,
1832		col: Partition<'LEFT, 'RIGHT, 'COLS>,
1833	) -> (
1834		MatRef<'a, T, Dim<'TOP>, Dim<'LEFT>, RStride, CStride>,
1835		MatRef<'a, T, Dim<'TOP>, Dim<'RIGHT>, RStride, CStride>,
1836		MatRef<'a, T, Dim<'BOT>, Dim<'LEFT>, RStride, CStride>,
1837		MatRef<'a, T, Dim<'BOT>, Dim<'RIGHT>, RStride, CStride>,
1838	) {
1839		let (a, b, c, d) = self.split_at(row.midpoint(), col.midpoint());
1840		(
1841			a.as_shape(row.head, col.head),
1842			b.as_shape(row.head, col.tail),
1843			c.as_shape(row.tail, col.head),
1844			d.as_shape(row.tail, col.tail),
1845		)
1846	}
1847}
1848impl<'ROWS, 'a, T, Cols: Shape, RStride: Stride, CStride: Stride>
1849	MatMut<'a, T, Dim<'ROWS>, Cols, RStride, CStride>
1850{
1851	#[doc(hidden)]
1852	#[inline]
1853	pub fn split_rows_with<'TOP, 'BOT>(
1854		self,
1855		row: Partition<'TOP, 'BOT, 'ROWS>,
1856	) -> (
1857		MatRef<'a, T, Dim<'TOP>, Cols, RStride, CStride>,
1858		MatRef<'a, T, Dim<'BOT>, Cols, RStride, CStride>,
1859	) {
1860		let (a, b) = self.split_at_row(row.midpoint());
1861		(a.as_row_shape(row.head), b.as_row_shape(row.tail))
1862	}
1863}
1864impl<'COLS, 'a, T, Rows: Shape, RStride: Stride, CStride: Stride>
1865	MatMut<'a, T, Rows, Dim<'COLS>, RStride, CStride>
1866{
1867	#[doc(hidden)]
1868	#[inline]
1869	pub fn split_cols_with<'LEFT, 'RIGHT>(
1870		self,
1871		col: Partition<'LEFT, 'RIGHT, 'COLS>,
1872	) -> (
1873		MatRef<'a, T, Rows, Dim<'LEFT>, RStride, CStride>,
1874		MatRef<'a, T, Rows, Dim<'RIGHT>, RStride, CStride>,
1875	) {
1876		let (a, b) = self.split_at_col(col.midpoint());
1877		(a.as_col_shape(col.head), b.as_col_shape(col.tail))
1878	}
1879}
1880impl<'a, T, Dim: Shape, RStride: Stride, CStride: Stride>
1881	MatMut<'a, T, Dim, Dim, RStride, CStride>
1882{
1883	/// see [`MatRef::diagonal`]
1884	#[inline]
1885	pub fn diagonal(self) -> DiagRef<'a, T, Dim, isize> {
1886		self.into_const().diagonal()
1887	}
1888}
1889impl<'a, T, Dim: Shape, RStride: Stride, CStride: Stride>
1890	MatMut<'a, T, Dim, Dim, RStride, CStride>
1891{
1892	/// see [`MatRef::diagonal`]
1893	#[inline]
1894	pub fn diagonal_mut(self) -> DiagMut<'a, T, Dim, isize> {
1895		unsafe {
1896			self.into_const()
1897				.diagonal()
1898				.column_vector()
1899				.const_cast()
1900				.as_diagonal_mut()
1901		}
1902	}
1903}
1904impl<
1905	'a,
1906	T: core::fmt::Debug,
1907	Rows: Shape,
1908	Cols: Shape,
1909	RStride: Stride,
1910	CStride: Stride,
1911> core::fmt::Debug for Mut<'a, T, Rows, Cols, RStride, CStride>
1912{
1913	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1914		self.rb().fmt(f)
1915	}
1916}
1917impl<'a, T, Rows: Shape, Cols: Shape> MatMut<'a, T, Rows, Cols>
1918where
1919	T: RealField,
1920{
1921	/// see [MatRef::min]
1922	pub fn min(self) -> Option<T> {
1923		MatRef::internal_min(self.rb().as_dyn())
1924	}
1925
1926	/// see [MatRef::min]
1927	pub fn max(self) -> Option<T> {
1928		MatRef::internal_max(self.rb().as_dyn())
1929	}
1930}
1931#[track_caller]
1932#[inline]
1933fn from_strided_column_major_slice_mut_assert(
1934	nrows: usize,
1935	ncols: usize,
1936	col_stride: usize,
1937	len: usize,
1938) {
1939	if nrows > 0 && ncols > 0 {
1940		let last = usize::checked_mul(col_stride, ncols - 1)
1941			.and_then(|last_col| last_col.checked_add(nrows - 1));
1942		let Some(last) = last else {
1943			panic!("address computation of the last matrix element overflowed");
1944		};
1945		assert!(all(col_stride >= nrows, last < len));
1946	}
1947}
1948#[track_caller]
1949#[inline]
1950fn from_strided_row_major_slice_mut_assert(
1951	nrows: usize,
1952	ncols: usize,
1953	row_stride: usize,
1954	len: usize,
1955) {
1956	if nrows > 0 && ncols > 0 {
1957		let last = usize::checked_mul(row_stride, nrows - 1)
1958			.and_then(|last_row| last_row.checked_add(ncols - 1));
1959		let Some(last) = last else {
1960			panic!("address computation of the last matrix element overflowed");
1961		};
1962		assert!(all(row_stride >= ncols, last < len));
1963	}
1964}
1965#[cfg(test)]
1966mod tests {
1967	use super::*;
1968	#[test]
1969	fn test_min() {
1970		let mut m = mat![[1.0, 5.0, 3.0], [4.0, 2.0, 9.0], [7.0, 8.0, 6.0],];
1971		assert_eq!(m.as_mut().min(), Some(1.0));
1972		let mut empty: Mat<f64> = Mat::new();
1973		assert_eq!(empty.as_mut().min(), None);
1974	}
1975	#[test]
1976	fn test_max() {
1977		let mut m = mat![[1.0, 5.0, 3.0], [4.0, 2.0, 9.0], [7.0, 8.0, 6.0],];
1978		assert_eq!(m.as_mut().max(), Some(9.0));
1979		let mut empty: Mat<f64> = Mat::new();
1980		assert_eq!(empty.as_mut().max(), None);
1981	}
1982}