faer/mat/
matmut.rs

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