Skip to main content

faer/mat/
matown.rs

1use super::*;
2use crate::internal_prelude::*;
3use crate::{Idx, IdxInc, TryReserveError, assert};
4use core::alloc::Layout;
5use dyn_stack::StackReq;
6use faer_traits::ComplexField;
7#[inline]
8pub(crate) fn align_for(size: usize, align: usize, needs_drop: bool) -> usize {
9	if needs_drop || !size.is_power_of_two() {
10		align
11	} else {
12		Ord::max(align, 64)
13	}
14}
15#[inline(never)]
16unsafe fn noalias_annotate<T, Rows: Shape, Cols: Shape>(
17	iter: &mut [core::mem::MaybeUninit<T>],
18	new_nrows: IdxInc<Rows>,
19	old_nrows: IdxInc<Rows>,
20	f: &mut impl FnMut(Idx<Rows>, Idx<Cols>) -> T,
21	j: Idx<Cols>,
22) {
23	let ptr = iter.as_mut_ptr();
24	let mut guard = DropCol {
25		ptr: ptr as *mut T,
26		nrows: 0,
27	};
28	for i in Rows::indices(old_nrows, new_nrows) {
29		let ptr = iter.as_mut_ptr().add(i.unbound()) as *mut T;
30		ptr.write((*f)(i, j));
31		guard.nrows += 1;
32	}
33	core::mem::forget(guard);
34}
35pub(crate) struct DropIter<I: Iterator>(pub I);
36impl<I: Iterator> Drop for DropIter<I> {
37	#[inline]
38	fn drop(&mut self) {
39		pub struct DropIterRetry<'a, I: Iterator>(pub &'a mut I);
40		impl<I: Iterator> Drop for DropIterRetry<'_, I> {
41			#[inline]
42			fn drop(&mut self) {
43				self.0.for_each(drop);
44			}
45		}
46		let in_case_of_panic = DropIterRetry(&mut self.0);
47		in_case_of_panic.0.for_each(drop);
48		core::mem::forget(in_case_of_panic);
49	}
50}
51extern crate alloc;
52struct RawMatUnit<T> {
53	ptr: NonNull<T>,
54	row_capacity: usize,
55	col_capacity: usize,
56	layout: StackReq,
57	__marker: PhantomData<T>,
58}
59struct RawMat<T> {
60	ptr: NonNull<T>,
61	row_capacity: usize,
62	col_capacity: usize,
63	layout: StackReq,
64	__marker: PhantomData<T>,
65}
66impl<T> RawMatUnit<T> {
67	fn try_with_capacity(
68		mut row_capacity: usize,
69		col_capacity: usize,
70	) -> Result<Self, TryReserveError> {
71		let size = core::mem::size_of::<T>();
72		let prev_align = core::mem::align_of::<T>();
73		let align = align_for(size, prev_align, core::mem::needs_drop::<T>());
74		if align > size {
75			row_capacity = row_capacity
76				.msrv_checked_next_multiple_of(align / size)
77				.ok_or(TryReserveError::CapacityOverflow)?;
78		}
79		let size = size
80			.checked_mul(row_capacity)
81			.and_then(|size| size.checked_mul(col_capacity))
82			.ok_or(TryReserveError::CapacityOverflow)?;
83		let layout;
84		let ptr = if size == 0 {
85			layout = StackReq::empty();
86			core::ptr::null_mut::<u8>().wrapping_add(align)
87		} else {
88			let new_layout = Layout::from_size_align(size, align)
89				.map_err(|_| TryReserveError::CapacityOverflow)?;
90			layout = StackReq::new_aligned::<u8>(
91				new_layout.size(),
92				new_layout.align(),
93			);
94			let ptr = unsafe { alloc::alloc::alloc(new_layout) };
95			if ptr.is_null() {
96				return Err(TryReserveError::AllocError { layout: new_layout });
97			}
98			ptr
99		};
100		let ptr = ptr as *mut T;
101		Ok(Self {
102			ptr: unsafe { NonNull::new_unchecked(ptr) },
103			row_capacity,
104			col_capacity,
105			layout,
106			__marker: PhantomData,
107		})
108	}
109
110	fn into_raw_parts(self) -> (NonNull<T>, usize, usize, StackReq) {
111		let this = core::mem::ManuallyDrop::new(self);
112		(this.ptr, this.row_capacity, this.col_capacity, this.layout)
113	}
114}
115impl<T> Drop for RawMatUnit<T> {
116	#[inline]
117	fn drop(&mut self) {
118		if self.layout.size_bytes() > 0 {
119			unsafe {
120				alloc::alloc::dealloc(
121					self.ptr.as_ptr() as *mut u8,
122					Layout::from_size_align_unchecked(
123						self.layout.size_bytes(),
124						self.layout.align_bytes(),
125					),
126				)
127			};
128		}
129	}
130}
131impl<T> RawMat<T> {
132	#[cold]
133	fn try_with_capacity(
134		row_capacity: usize,
135		col_capacity: usize,
136	) -> Result<Self, TryReserveError> {
137		let mut err = None;
138		let alloc = {
139			let alloc =
140				RawMatUnit::<T>::try_with_capacity(row_capacity, col_capacity);
141			if let Err(alloc_err) = &alloc {
142				err = Some(*alloc_err);
143			}
144			alloc
145		};
146		if let Some(err) = err {
147			return Err(err);
148		}
149		let layout;
150		let row_capacity;
151		let ptr = {
152			let (ptr, new_row_capacity, _, unit_layout) =
153				alloc.unwrap().into_raw_parts();
154			row_capacity = new_row_capacity;
155			layout = unit_layout;
156			ptr
157		};
158		Ok(Self {
159			ptr,
160			row_capacity,
161			col_capacity,
162			layout,
163			__marker: PhantomData,
164		})
165	}
166
167	#[cold]
168	fn do_reserve_with(
169		&mut self,
170		nrows: usize,
171		ncols: usize,
172		new_row_capacity: usize,
173		new_col_capacity: usize,
174	) -> Result<(), TryReserveError> {
175		let old_row_capacity = self.row_capacity;
176		let size = core::mem::size_of::<T>();
177		let new = Self::try_with_capacity(new_row_capacity, new_col_capacity)?;
178		let new_row_capacity = new.row_capacity;
179		unsafe fn move_mat(
180			mut new: *mut u8,
181			mut old: *const u8,
182			col_bytes: usize,
183			ncols: usize,
184			new_byte_stride: isize,
185			old_byte_stride: isize,
186		) {
187			for _ in 0..ncols {
188				core::ptr::copy_nonoverlapping(old, new, col_bytes);
189				new = new.wrapping_offset(new_byte_stride);
190				old = old.wrapping_offset(old_byte_stride);
191			}
192		}
193		{
194			let new = new.ptr;
195			let old = self.ptr;
196			let new = new.as_ptr() as *mut u8;
197			let old = old.as_ptr() as *const u8;
198			unsafe {
199				move_mat(
200					new,
201					old,
202					nrows * size,
203					ncols,
204					(new_row_capacity * size) as isize,
205					(old_row_capacity * size) as isize,
206				)
207			};
208		};
209		*self = new;
210		Ok(())
211	}
212
213	fn try_reserve(
214		&mut self,
215		nrows: usize,
216		ncols: usize,
217		new_row_capacity: usize,
218		new_col_capacity: usize,
219	) -> Result<(), TryReserveError> {
220		let new_row_capacity = Ord::max(new_row_capacity, nrows);
221		let new_col_capacity = Ord::max(new_col_capacity, ncols);
222		if new_row_capacity > self.row_capacity
223			|| new_col_capacity > self.col_capacity
224		{
225			self.do_reserve_with(
226				nrows,
227				ncols,
228				new_row_capacity,
229				new_col_capacity,
230			)?
231		}
232		Ok(())
233	}
234}
235impl<T> Drop for RawMat<T> {
236	fn drop(&mut self) {
237		let ptr = self.ptr;
238		drop(RawMatUnit {
239			ptr,
240			row_capacity: self.row_capacity,
241			col_capacity: self.col_capacity,
242			layout: self.layout,
243			__marker: PhantomData,
244		});
245	}
246}
247/// see [`super::Mat`]
248pub struct Own<T, Rows: Shape = usize, Cols: Shape = usize> {
249	raw: RawMat<T>,
250	nrows: Rows,
251	ncols: Cols,
252}
253unsafe impl<T: Send, Rows: Shape, Cols: Shape> Send for Own<T, Rows, Cols> {}
254unsafe impl<T: Sync, Rows: Shape, Cols: Shape> Sync for Own<T, Rows, Cols> {}
255pub(crate) struct DropCol<T> {
256	ptr: *mut T,
257	nrows: usize,
258}
259pub(crate) struct DropMat<T> {
260	ptr: *mut T,
261	nrows: usize,
262	ncols: usize,
263	byte_col_stride: usize,
264}
265impl<T> Drop for DropCol<T> {
266	#[inline]
267	fn drop(&mut self) {
268		if const { core::mem::needs_drop::<T>() } {
269			unsafe {
270				let slice =
271					core::slice::from_raw_parts_mut(self.ptr, self.nrows);
272				core::ptr::drop_in_place(slice);
273			}
274		}
275	}
276}
277impl<T> Drop for DropMat<T> {
278	#[inline]
279	fn drop(&mut self) {
280		if const { core::mem::needs_drop::<T>() } {
281			let mut ptr = self.ptr;
282			if self.nrows > 0 {
283				DropIter((0..self.ncols).map(|_| {
284					DropCol {
285						ptr,
286						nrows: self.nrows,
287					};
288					ptr = ptr.wrapping_byte_add(self.byte_col_stride);
289				}));
290			}
291		}
292	}
293}
294impl<T, Rows: Shape, Cols: Shape> Drop for Own<T, Rows, Cols> {
295	#[inline]
296	fn drop(&mut self) {
297		if const { core::mem::needs_drop::<T>() } {
298			if self.nrows.unbound() > 0 && self.ncols.unbound() > 0 {
299				let size = core::mem::size_of::<T>();
300				let ptr = self.raw.ptr.as_ptr();
301				let row_capacity = self.raw.row_capacity;
302				let stride = row_capacity * size;
303				drop(DropMat {
304					ptr,
305					nrows: self.nrows.unbound(),
306					ncols: self.ncols.unbound(),
307					byte_col_stride: stride,
308				})
309			}
310		}
311	}
312}
313impl<T> Mat<T> {
314	/// returns an empty matrix of dimension `0×0`.
315	#[inline]
316	pub const fn new() -> Self {
317		Self(Own {
318			raw: RawMat {
319				ptr: NonNull::dangling(),
320				row_capacity: 0,
321				col_capacity: 0,
322				layout: StackReq::EMPTY,
323				__marker: PhantomData,
324			},
325			nrows: 0,
326			ncols: 0,
327		})
328	}
329
330	/// reserves the minimum capacity for `row_capacity` rows and `col_capacity`
331	/// columns without reallocating. does nothing if the capacity is already
332	/// sufficient
333	#[track_caller]
334	pub fn with_capacity(row_capacity: usize, col_capacity: usize) -> Self {
335		let mut me = Self::new();
336		me.reserve(row_capacity, col_capacity);
337		me
338	}
339}
340impl<T, Rows: Shape, Cols: Shape> Mat<T, Rows, Cols> {
341	unsafe fn init_with(
342		ptr: *mut T,
343		old_nrows: IdxInc<Rows>,
344		old_ncols: IdxInc<Cols>,
345		new_nrows: IdxInc<Rows>,
346		new_ncols: IdxInc<Cols>,
347		row_capacity: usize,
348		f: &mut impl FnMut(Idx<Rows>, Idx<Cols>) -> T,
349	) {
350		let stride = row_capacity;
351		let mut ptr = ptr.wrapping_add(stride * old_ncols.unbound());
352		let mut col_guard = DropMat {
353			ptr,
354			nrows: new_nrows.unbound() - old_nrows.unbound(),
355			ncols: 0,
356			byte_col_stride: stride,
357		};
358		for j in Cols::indices(old_ncols, new_ncols) {
359			let old = ptr;
360			noalias_annotate::<T, Rows, Cols>(
361				core::slice::from_raw_parts_mut(
362					ptr as *mut _,
363					new_nrows.unbound(),
364				),
365				new_nrows,
366				old_nrows,
367				f,
368				j,
369			);
370			col_guard.ncols += 1;
371			ptr = old.wrapping_add(stride);
372		}
373		core::mem::forget(col_guard);
374	}
375
376	/// returns a new matrix with dimensions `(nrows, ncols)`, filled with the
377	/// provided function
378	pub fn from_fn(
379		nrows: Rows,
380		ncols: Cols,
381		f: impl FnMut(Idx<Rows>, Idx<Cols>) -> T,
382	) -> Self {
383		unsafe {
384			let raw = RawMat::<T>::try_with_capacity(
385				nrows.unbound(),
386				ncols.unbound(),
387			)
388			.unwrap();
389			let ptr = raw.ptr.as_ptr();
390			Self::init_with(
391				ptr,
392				Rows::start(),
393				Cols::start(),
394				nrows.end(),
395				ncols.end(),
396				raw.row_capacity,
397				&mut { f },
398			);
399			Self(Own { raw, nrows, ncols })
400		}
401	}
402
403	/// returns a new matrix with dimensions `(nrows, ncols)`, filled with zeros
404	#[inline]
405	pub fn zeros(nrows: Rows, ncols: Cols) -> Self
406	where
407		T: ComplexField,
408	{
409		Self::from_fn(nrows, ncols, |_, _| T::zero_impl())
410	}
411
412	/// returns a new matrix with dimensions `(nrows, ncols)`, filled with ones
413	#[inline]
414	pub fn ones(nrows: Rows, ncols: Cols) -> Self
415	where
416		T: ComplexField,
417	{
418		Self::from_fn(nrows, ncols, |_, _| T::one_impl())
419	}
420
421	/// returns a new identity matrix, with ones on the diagonal and zeros
422	/// everywhere else
423	#[inline]
424	pub fn identity(nrows: Rows, ncols: Cols) -> Self
425	where
426		T: ComplexField,
427	{
428		Self::from_fn(nrows, ncols, |i, j| {
429			if i.unbound() == j.unbound() {
430				T::one_impl()
431			} else {
432				T::zero_impl()
433			}
434		})
435	}
436
437	/// returns a new matrix with dimensions `(nrows, ncols)`, filled with
438	/// `value`
439	#[inline]
440	pub fn full(nrows: Rows, ncols: Cols, value: T) -> Self
441	where
442		T: Clone,
443	{
444		Self::from_fn(nrows, ncols, |_, _| value.clone())
445	}
446
447	/// reserves the minimum capacity for `new_row_capacity` rows and
448	/// `new_col_capacity` columns without reallocating, or returns an error in
449	/// case of failure. does nothing if the capacity is already sufficient
450	pub fn try_reserve(
451		&mut self,
452		new_row_capacity: usize,
453		new_col_capacity: usize,
454	) -> Result<(), TryReserveError> {
455		self.0.raw.try_reserve(
456			self.0.nrows.unbound(),
457			self.0.ncols.unbound(),
458			new_row_capacity,
459			new_col_capacity,
460		)
461	}
462
463	/// reserves the minimum capacity for `new_row_capacity` rows and
464	/// `new_col_capacity` columns without reallocating. does nothing if the
465	/// capacity is already sufficient
466	#[track_caller]
467	pub fn reserve(
468		&mut self,
469		new_row_capacity: usize,
470		new_col_capacity: usize,
471	) {
472		self.try_reserve(new_row_capacity, new_col_capacity)
473			.unwrap()
474	}
475
476	/// resizes the matrix in-place so that the new dimensions are `(new_nrows,
477	/// new_ncols)`. new elements are created with the given function `f`, so
478	/// that elements at index `(i, j)` are created by calling `f(i, j)`.
479	pub fn resize_with(
480		&mut self,
481		new_nrows: Rows,
482		new_ncols: Cols,
483		f: impl FnMut(Idx<Rows>, Idx<Cols>) -> T,
484	) {
485		unsafe {
486			let this = &mut *self;
487			if new_nrows == this.0.nrows && new_ncols == this.0.ncols {
488				return;
489			}
490			this.truncate(new_nrows, new_ncols);
491			if new_nrows > this.0.nrows || new_ncols > this.0.ncols {
492				this.reserve(new_nrows.unbound(), new_ncols.unbound());
493			}
494			let mut f = f;
495			if new_nrows > this.0.nrows {
496				Self::init_with(
497					this.0.raw.ptr.as_ptr(),
498					this.0.nrows.end(),
499					Cols::start(),
500					new_nrows.end(),
501					this.0.ncols.end(),
502					this.0.raw.row_capacity,
503					&mut f,
504				);
505				this.0.nrows = new_nrows;
506			}
507			if new_ncols > this.0.ncols {
508				Self::init_with(
509					this.0.raw.ptr.as_ptr(),
510					Rows::start(),
511					this.0.ncols.end(),
512					new_nrows.end(),
513					new_ncols.end(),
514					this.0.raw.row_capacity,
515					&mut f,
516				);
517				this.0.ncols = new_ncols;
518			}
519		};
520	}
521
522	/// truncates the matrix so that its new dimensions are `new_nrows` and
523	/// `new_ncols`. both of the new dimensions must be smaller than or equal
524	/// to the current dimensions
525	///
526	/// # panics
527	/// the function panics if any of the following conditions are violated:
528	/// - `new_nrows > self.nrows()`
529	/// - `new_ncols > self.ncols()`
530	pub fn truncate(&mut self, new_nrows: Rows, new_ncols: Cols) {
531		if new_ncols < self.0.ncols {
532			let stride = self.0.raw.row_capacity;
533			drop(DropMat {
534				ptr: self
535					.0
536					.raw
537					.ptr
538					.as_ptr()
539					.wrapping_add(stride * new_ncols.unbound()),
540				nrows: self.0.nrows.unbound(),
541				ncols: self.0.ncols.unbound() - new_ncols.unbound(),
542				byte_col_stride: stride,
543			});
544			self.0.ncols = new_ncols;
545		}
546		if new_nrows < self.0.nrows {
547			let size = core::mem::size_of::<T>();
548			let stride = size * self.0.raw.row_capacity;
549			drop(DropMat {
550				ptr: self.0.raw.ptr.as_ptr().wrapping_add(new_nrows.unbound()),
551				nrows: self.0.nrows.unbound() - new_nrows.unbound(),
552				ncols: self.0.ncols.unbound(),
553				byte_col_stride: stride,
554			});
555			self.0.nrows = new_nrows;
556		}
557	}
558
559	/// see [`MatRef::as_shape`]
560	#[track_caller]
561	pub fn into_shape<V: Shape, H: Shape>(
562		self,
563		nrows: V,
564		ncols: H,
565	) -> Mat<T, V, H> {
566		assert!(all(
567			self.nrows().unbound() == nrows.unbound(),
568			self.ncols().unbound() == ncols.unbound()
569		));
570		let this = core::mem::ManuallyDrop::new(self);
571		Mat {
572			0: Own {
573				raw: RawMat {
574					ptr: this.0.raw.ptr,
575					row_capacity: this.0.raw.row_capacity,
576					col_capacity: this.0.raw.col_capacity,
577					layout: this.0.raw.layout,
578					__marker: PhantomData,
579				},
580				nrows,
581				ncols,
582			},
583		}
584	}
585
586	/// set the dimensions of the matrix.
587	///
588	/// # safety
589	/// the behavior is undefined if any of the following conditions are
590	/// violated:
591	/// - `nrows < self.row_capacity()`
592	/// - `ncols < self.col_capacity()`
593	/// - the elements that were previously out of bounds but are now in bounds
594	///   must be
595	/// initialized
596	pub unsafe fn set_dims(&mut self, nrows: Rows, ncols: Cols) {
597		self.0.nrows = nrows;
598		self.0.ncols = ncols;
599	}
600
601	/// returns a reference to a slice over the column at the given index
602	pub fn col_as_slice(&self, j: Idx<Cols>) -> &[T] {
603		self.col(j).try_as_col_major().unwrap().as_slice()
604	}
605
606	/// returns a reference to a slice over the column at the given index
607	pub fn col_as_slice_mut(&mut self, j: Idx<Cols>) -> &mut [T] {
608		self.col_mut(j)
609			.try_as_col_major_mut()
610			.unwrap()
611			.as_slice_mut()
612	}
613}
614impl<T, Rows: Shape, Cols: Shape> Mat<T, Rows, Cols> {
615	/// returns the number of rows of the matrix
616	#[inline]
617	pub fn nrows(&self) -> Rows {
618		self.0.nrows
619	}
620
621	/// returns the number of columns of the matrix
622	#[inline]
623	pub fn ncols(&self) -> Cols {
624		self.0.ncols
625	}
626}
627impl<T: Clone, Rows: Shape, Cols: Shape> Clone for Own<T, Rows, Cols> {
628	#[inline]
629	fn clone(&self) -> Self {
630		let __self__ = Mat::from_inner_ref(self);
631		with_dim!(M, __self__.nrows().unbound());
632		with_dim!(N, __self__.ncols().unbound());
633		let this = __self__.as_ref().as_shape(M, N);
634		Mat::from_fn(this.nrows(), this.ncols(), |i, j| this.at(i, j).clone())
635			.into_shape(__self__.nrows(), __self__.ncols())
636			.0
637	}
638}
639impl<T: core::fmt::Debug, Rows: Shape, Cols: Shape> core::fmt::Debug
640	for Own<T, Rows, Cols>
641{
642	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
643		self.rb().fmt(f)
644	}
645}
646impl<T, Rows: Shape, Cols: Shape> Mat<T, Rows, Cols> {
647	/// returns a pointer to the matrix data
648	#[inline(always)]
649	pub fn as_ptr(&self) -> *const T {
650		self.as_ref().as_ptr()
651	}
652
653	/// returns the number of rows and columns of the matrix
654	#[inline(always)]
655	pub fn shape(&self) -> (Rows, Cols) {
656		(self.nrows(), self.ncols())
657	}
658
659	/// returns the row stride of the matrix, specified in number of elements,
660	/// not in bytes
661	#[inline(always)]
662	pub fn row_stride(&self) -> isize {
663		1
664	}
665
666	/// returns the column stride of the matrix, specified in number of
667	/// elements, not in bytes
668	#[inline(always)]
669	pub fn col_stride(&self) -> isize {
670		self.0.raw.row_capacity as isize
671	}
672
673	#[inline]
674	pub fn map<U>(&self, f: impl Fn(&T) -> U) -> Mat<U, Rows, Cols> {
675		self.rb().map(f)
676	}
677
678	#[inline]
679	pub fn for_each(&self, f: impl Fn(&T)) {
680		self.rb().for_each(f)
681	}
682
683	#[inline]
684	pub fn map_mut<U>(
685		&mut self,
686		f: impl FnMut(&mut T) -> U,
687	) -> Mat<U, Rows, Cols> {
688		self.rb_mut().map_mut(f)
689	}
690
691	#[inline]
692	pub fn for_each_mut(&mut self, f: impl FnMut(&mut T)) {
693		self.rb_mut().for_each_mut(f)
694	}
695
696	/// returns a raw pointer to the element at the given index
697	#[inline(always)]
698	pub fn ptr_at(&self, row: IdxInc<Rows>, col: IdxInc<Cols>) -> *const T {
699		self.as_ref().ptr_at(row, col)
700	}
701
702	/// returns a raw pointer to the element at the given index, assuming the
703	/// provided index is within the matrix bounds
704	///
705	/// # safety
706	/// the behavior is undefined if any of the following conditions are
707	/// violated:
708	/// * `row < self.nrows()`
709	/// * `col < self.ncols()`
710	#[inline(always)]
711	#[track_caller]
712	pub unsafe fn ptr_inbounds_at(
713		&self,
714		row: Idx<Rows>,
715		col: Idx<Cols>,
716	) -> *const T {
717		self.as_ref().ptr_inbounds_at(row, col)
718	}
719
720	#[inline]
721	#[track_caller]
722	/// see [`MatRef::split_at`]
723	pub fn split_at(
724		&self,
725		row: IdxInc<Rows>,
726		col: IdxInc<Cols>,
727	) -> (
728		MatRef<'_, T, usize, usize>,
729		MatRef<'_, T, usize, usize>,
730		MatRef<'_, T, usize, usize>,
731		MatRef<'_, T, usize, usize>,
732	) {
733		self.as_ref().split_at(row, col)
734	}
735
736	#[inline]
737	#[track_caller]
738	/// see [`MatRef::split_at_row`]
739	pub fn split_at_row(
740		&self,
741		row: IdxInc<Rows>,
742	) -> (MatRef<'_, T, usize, Cols>, MatRef<'_, T, usize, Cols>) {
743		self.as_ref().split_at_row(row)
744	}
745
746	#[inline]
747	#[track_caller]
748	/// see [`MatRef::split_at_col`]
749	pub fn split_at_col(
750		&self,
751		col: IdxInc<Cols>,
752	) -> (MatRef<'_, T, Rows, usize>, MatRef<'_, T, Rows, usize>) {
753		self.as_ref().split_at_col(col)
754	}
755
756	#[inline(always)]
757	/// see [`MatRef::transpose`]
758	pub fn transpose(&self) -> MatRef<'_, T, Cols, Rows> {
759		self.as_ref().transpose()
760	}
761
762	#[inline(always)]
763	/// see [`MatRef::conjugate`]
764	pub fn conjugate(&self) -> MatRef<'_, T::Conj, Rows, Cols>
765	where
766		T: Conjugate,
767	{
768		self.as_ref().conjugate()
769	}
770
771	#[inline(always)]
772	/// see [`MatRef::canonical`]
773	pub fn canonical(&self) -> MatRef<'_, T::Canonical, Rows, Cols>
774	where
775		T: Conjugate,
776	{
777		self.as_ref().canonical()
778	}
779
780	#[inline(always)]
781	/// see [`MatRef::adjoint`]
782	pub fn adjoint(&self) -> MatRef<'_, T::Conj, Cols, Rows>
783	where
784		T: Conjugate,
785	{
786		self.as_ref().adjoint()
787	}
788
789	#[inline]
790	/// see [`MatRef::reverse_rows`]
791	pub fn reverse_rows(&self) -> MatRef<'_, T, Rows, Cols> {
792		self.as_ref().reverse_rows()
793	}
794
795	#[inline]
796	/// see [`MatRef::reverse_cols`]
797	pub fn reverse_cols(&self) -> MatRef<'_, T, Rows, Cols> {
798		self.as_ref().reverse_cols()
799	}
800
801	#[inline]
802	/// see [`MatRef::reverse_rows_and_cols`]
803	pub fn reverse_rows_and_cols(&self) -> MatRef<'_, T, Rows, Cols> {
804		self.as_ref().reverse_rows_and_cols()
805	}
806
807	#[inline]
808	/// see [`MatRef::submatrix`]
809	pub fn submatrix<V: Shape, H: Shape>(
810		&self,
811		row_start: IdxInc<Rows>,
812		col_start: IdxInc<Cols>,
813		nrows: V,
814		ncols: H,
815	) -> MatRef<'_, T, V, H> {
816		self.as_ref().submatrix(row_start, col_start, nrows, ncols)
817	}
818
819	#[inline]
820	/// see [`MatRef::subrows`]
821	pub fn subrows<V: Shape>(
822		&self,
823		row_start: IdxInc<Rows>,
824		nrows: V,
825	) -> MatRef<'_, T, V, Cols> {
826		self.as_ref().subrows(row_start, nrows)
827	}
828
829	#[inline]
830	/// see [`MatRef::subcols`]
831	pub fn subcols<H: Shape>(
832		&self,
833		col_start: IdxInc<Cols>,
834		ncols: H,
835	) -> MatRef<'_, T, Rows, H> {
836		self.as_ref().subcols(col_start, ncols)
837	}
838
839	#[inline]
840	/// see [`MatRef::as_shape`]
841	pub fn as_shape<V: Shape, H: Shape>(
842		&self,
843		nrows: V,
844		ncols: H,
845	) -> MatRef<'_, T, V, H> {
846		self.as_ref().as_shape(nrows, ncols)
847	}
848
849	#[inline]
850	/// see [`MatRef::as_row_shape`]
851	pub fn as_row_shape<V: Shape>(&self, nrows: V) -> MatRef<'_, T, V, Cols> {
852		self.as_ref().as_row_shape(nrows)
853	}
854
855	#[inline]
856	/// see [`MatRef::as_col_shape`]
857	pub fn as_col_shape<H: Shape>(&self, ncols: H) -> MatRef<'_, T, Rows, H> {
858		self.as_ref().as_col_shape(ncols)
859	}
860
861	#[inline]
862	/// see [`MatRef::as_dyn_stride`]
863	pub fn as_dyn_stride(&self) -> MatRef<'_, T, Rows, Cols, isize, isize> {
864		self.as_ref().as_dyn_stride()
865	}
866
867	#[inline]
868	/// see [`MatRef::as_dyn`]
869	pub fn as_dyn(&self) -> MatRef<'_, T, usize, usize> {
870		self.as_ref().as_dyn()
871	}
872
873	#[inline]
874	/// see [`MatRef::as_dyn_rows`]
875	pub fn as_dyn_rows(&self) -> MatRef<'_, T, usize, Cols> {
876		self.as_ref().as_dyn_rows()
877	}
878
879	#[inline]
880	/// see [`MatRef::as_dyn_cols`]
881	pub fn as_dyn_cols(&self) -> MatRef<'_, T, Rows, usize> {
882		self.as_ref().as_dyn_cols()
883	}
884
885	#[inline]
886	/// see [`MatRef::row`]
887	pub fn row(&self, i: Idx<Rows>) -> RowRef<'_, T, Cols> {
888		self.as_ref().row(i)
889	}
890
891	#[inline]
892	#[track_caller]
893	/// see [`MatRef::col`]
894	pub fn col(&self, j: Idx<Cols>) -> ColRef<'_, T, Rows> {
895		self.as_ref().col(j)
896	}
897
898	#[inline]
899	/// see [`MatRef::col_iter`]
900	pub fn col_iter(
901		&self,
902	) -> impl '_ + ExactSizeIterator + DoubleEndedIterator<Item = ColRef<'_, T, Rows>>
903	{
904		self.as_ref().col_iter()
905	}
906
907	#[inline]
908	/// see [`MatRef::row_iter`]
909	pub fn row_iter(
910		&self,
911	) -> impl '_ + ExactSizeIterator + DoubleEndedIterator<Item = RowRef<'_, T, Cols>>
912	{
913		self.as_ref().row_iter()
914	}
915
916	#[inline]
917	#[track_caller]
918	#[cfg(feature = "rayon")]
919	/// see [`MatRef::par_col_iter`]
920	pub fn par_col_iter(
921		&self,
922	) -> impl '_ + rayon::iter::IndexedParallelIterator<Item = ColRef<'_, T, Rows>>
923	where
924		T: Sync,
925	{
926		self.as_ref().par_col_iter()
927	}
928
929	#[inline]
930	#[track_caller]
931	#[cfg(feature = "rayon")]
932	/// see [`MatRef::par_row_iter`]
933	pub fn par_row_iter(
934		&self,
935	) -> impl '_ + rayon::iter::IndexedParallelIterator<Item = RowRef<'_, T, Cols>>
936	where
937		T: Sync,
938	{
939		self.as_ref().par_row_iter()
940	}
941
942	#[inline]
943	#[track_caller]
944	#[cfg(feature = "rayon")]
945	/// see [`MatRef::par_col_chunks`]
946	pub fn par_col_chunks(
947		&self,
948		chunk_size: usize,
949	) -> impl '_
950	+ rayon::iter::IndexedParallelIterator<
951		Item = MatRef<'_, T, Rows, usize>,
952	>
953	where
954		T: Sync,
955	{
956		self.as_ref().par_col_chunks(chunk_size)
957	}
958
959	#[inline]
960	#[track_caller]
961	#[cfg(feature = "rayon")]
962	/// see [`MatRef::par_col_partition`]
963	pub fn par_col_partition(
964		&self,
965		count: usize,
966	) -> impl '_
967	+ rayon::iter::IndexedParallelIterator<
968		Item = MatRef<'_, T, Rows, usize>,
969	>
970	where
971		T: Sync,
972	{
973		self.as_ref().par_col_partition(count)
974	}
975
976	#[inline]
977	#[track_caller]
978	#[cfg(feature = "rayon")]
979	/// see [`MatRef::par_row_chunks`]
980	pub fn par_row_chunks(
981		&self,
982		chunk_size: usize,
983	) -> impl '_
984	+ rayon::iter::IndexedParallelIterator<
985		Item = MatRef<'_, T, usize, Cols>,
986	>
987	where
988		T: Sync,
989	{
990		self.as_ref().par_row_chunks(chunk_size)
991	}
992
993	#[inline]
994	#[track_caller]
995	#[cfg(feature = "rayon")]
996	/// see [`MatRef::par_row_partition`]
997	pub fn par_row_partition(
998		&self,
999		count: usize,
1000	) -> impl '_
1001	+ rayon::iter::IndexedParallelIterator<
1002		Item = MatRef<'_, T, usize, Cols>,
1003	>
1004	where
1005		T: Sync,
1006	{
1007		self.as_ref().par_row_partition(count)
1008	}
1009
1010	#[inline]
1011	/// see [`MatRef::try_as_col_major`]
1012	pub fn try_as_col_major(
1013		&self,
1014	) -> Option<MatRef<'_, T, Rows, Cols, ContiguousFwd>> {
1015		self.as_ref().try_as_col_major()
1016	}
1017
1018	#[inline]
1019	/// see [`MatRef::try_as_row_major`]
1020	pub fn try_as_row_major(
1021		&self,
1022	) -> Option<MatRef<'_, T, Rows, Cols, isize, ContiguousFwd>> {
1023		self.as_ref().try_as_row_major()
1024	}
1025
1026	#[track_caller]
1027	#[inline]
1028	/// see [`MatRef::get`]
1029	pub fn get<RowRange, ColRange>(
1030		&self,
1031		row: RowRange,
1032		col: ColRange,
1033	) -> <MatRef<'_, T, Rows, Cols> as MatIndex<RowRange, ColRange>>::Target
1034	where
1035		for<'a> MatRef<'a, T, Rows, Cols>: MatIndex<RowRange, ColRange>,
1036	{
1037		<MatRef<'_, T, Rows, Cols> as MatIndex<RowRange, ColRange>>::get(
1038			self.as_ref(),
1039			row,
1040			col,
1041		)
1042	}
1043
1044	#[track_caller]
1045	#[inline]
1046	/// see [`MatRef::get_unchecked`]
1047	pub unsafe fn get_unchecked<RowRange, ColRange>(
1048		&self,
1049		row: RowRange,
1050		col: ColRange,
1051	) -> <MatRef<'_, T, Rows, Cols> as MatIndex<RowRange, ColRange>>::Target
1052	where
1053		for<'a> MatRef<'a, T, Rows, Cols>: MatIndex<RowRange, ColRange>,
1054	{
1055		unsafe {
1056			<MatRef<'_, T, Rows, Cols> as MatIndex<RowRange, ColRange>>::get_unchecked(self.as_ref(), row, col)
1057		}
1058	}
1059
1060	#[track_caller]
1061	#[inline]
1062	/// see [`MatMut::get_mut`]
1063	pub fn get_mut<RowRange, ColRange>(
1064		&mut self,
1065		row: RowRange,
1066		col: ColRange,
1067	) -> <MatMut<'_, T, Rows, Cols> as MatIndex<RowRange, ColRange>>::Target
1068	where
1069		for<'a> MatMut<'a, T, Rows, Cols>: MatIndex<RowRange, ColRange>,
1070	{
1071		<MatMut<'_, T, Rows, Cols> as MatIndex<RowRange, ColRange>>::get(
1072			self.as_mut(),
1073			row,
1074			col,
1075		)
1076	}
1077
1078	#[track_caller]
1079	#[inline]
1080	/// see [`MatMut::get_mut_unchecked`]
1081	pub unsafe fn get_mut_unchecked<RowRange, ColRange>(
1082		&mut self,
1083		row: RowRange,
1084		col: ColRange,
1085	) -> <MatMut<'_, T, Rows, Cols> as MatIndex<RowRange, ColRange>>::Target
1086	where
1087		for<'a> MatMut<'a, T, Rows, Cols>: MatIndex<RowRange, ColRange>,
1088	{
1089		unsafe {
1090			<MatMut<'_, T, Rows, Cols> as MatIndex<RowRange, ColRange>>::get_unchecked(self.as_mut(), row, col)
1091		}
1092	}
1093}
1094impl<T, Rows: Shape, Cols: Shape> Mat<T, Rows, Cols> {
1095	#[inline(always)]
1096	/// returns a pointer to the matrix data
1097	pub fn as_ptr_mut(&mut self) -> *mut T {
1098		self.as_mut().as_ptr_mut()
1099	}
1100
1101	#[inline(always)]
1102	/// returns a raw pointer to the element at the given index
1103	pub fn ptr_at_mut(
1104		&mut self,
1105		row: IdxInc<Rows>,
1106		col: IdxInc<Cols>,
1107	) -> *mut T {
1108		self.as_mut().ptr_at_mut(row, col)
1109	}
1110
1111	#[inline(always)]
1112	#[track_caller]
1113	/// returns a raw pointer to the element at the given index, assuming the
1114	/// provided index is within the matrix bounds
1115	///
1116	/// # safety
1117	/// the behavior is undefined if any of the following conditions are
1118	/// violated:
1119	/// * `row < self.nrows()`
1120	/// * `col < self.ncols()`
1121	pub unsafe fn ptr_inbounds_at_mut(
1122		&mut self,
1123		row: Idx<Rows>,
1124		col: Idx<Cols>,
1125	) -> *mut T {
1126		self.as_mut().ptr_inbounds_at_mut(row, col)
1127	}
1128
1129	#[inline]
1130	#[track_caller]
1131	/// see [`MatMut::split_at_mut`]
1132	pub fn split_at_mut(
1133		&mut self,
1134		row: IdxInc<Rows>,
1135		col: IdxInc<Cols>,
1136	) -> (
1137		MatMut<'_, T, usize, usize>,
1138		MatMut<'_, T, usize, usize>,
1139		MatMut<'_, T, usize, usize>,
1140		MatMut<'_, T, usize, usize>,
1141	) {
1142		self.as_mut().split_at_mut(row, col)
1143	}
1144
1145	#[inline]
1146	#[track_caller]
1147	/// see [`MatMut::split_at_row_mut`]
1148	pub fn split_at_row_mut(
1149		&mut self,
1150		row: IdxInc<Rows>,
1151	) -> (MatMut<'_, T, usize, Cols>, MatMut<'_, T, usize, Cols>) {
1152		self.as_mut().split_at_row_mut(row)
1153	}
1154
1155	#[inline]
1156	#[track_caller]
1157	/// see [`MatMut::split_at_col_mut`]
1158	pub fn split_at_col_mut(
1159		&mut self,
1160		col: IdxInc<Cols>,
1161	) -> (MatMut<'_, T, Rows, usize>, MatMut<'_, T, Rows, usize>) {
1162		self.as_mut().split_at_col_mut(col)
1163	}
1164
1165	#[inline(always)]
1166	/// see [`MatMut::transpose_mut`]
1167	pub fn transpose_mut(&mut self) -> MatMut<'_, T, Cols, Rows> {
1168		self.as_mut().transpose_mut()
1169	}
1170
1171	#[inline(always)]
1172	/// see [`MatMut::conjugate_mut`]
1173	pub fn conjugate_mut(&mut self) -> MatMut<'_, T::Conj, Rows, Cols>
1174	where
1175		T: Conjugate,
1176	{
1177		self.as_mut().conjugate_mut()
1178	}
1179
1180	#[inline(always)]
1181	/// see [`MatMut::canonical_mut`]
1182	pub fn canonical_mut(&mut self) -> MatMut<'_, T::Canonical, Rows, Cols>
1183	where
1184		T: Conjugate,
1185	{
1186		self.as_mut().canonical_mut()
1187	}
1188
1189	#[inline(always)]
1190	/// see [`MatMut::adjoint_mut`]
1191	pub fn adjoint_mut(&mut self) -> MatMut<'_, T::Conj, Cols, Rows>
1192	where
1193		T: Conjugate,
1194	{
1195		self.as_mut().adjoint_mut()
1196	}
1197
1198	#[inline]
1199	/// see [`MatMut::reverse_rows_mut`]
1200	pub fn reverse_rows_mut(&mut self) -> MatMut<'_, T, Rows, Cols> {
1201		self.as_mut().reverse_rows_mut()
1202	}
1203
1204	#[inline]
1205	/// see [`MatMut::reverse_cols_mut`]
1206	pub fn reverse_cols_mut(&mut self) -> MatMut<'_, T, Rows, Cols> {
1207		self.as_mut().reverse_cols_mut()
1208	}
1209
1210	#[inline]
1211	/// see [`MatMut::reverse_rows_and_cols_mut`]
1212	pub fn reverse_rows_and_cols_mut(&mut self) -> MatMut<'_, T, Rows, Cols> {
1213		self.as_mut().reverse_rows_and_cols_mut()
1214	}
1215
1216	#[inline]
1217	/// see [`MatMut::submatrix_mut`]
1218	pub fn submatrix_mut<V: Shape, H: Shape>(
1219		&mut self,
1220		row_start: IdxInc<Rows>,
1221		col_start: IdxInc<Cols>,
1222		nrows: V,
1223		ncols: H,
1224	) -> MatMut<'_, T, V, H> {
1225		self.as_mut()
1226			.submatrix_mut(row_start, col_start, nrows, ncols)
1227	}
1228
1229	#[inline]
1230	/// see [`MatMut::subrows_mut`]
1231	pub fn subrows_mut<V: Shape>(
1232		&mut self,
1233		row_start: IdxInc<Rows>,
1234		nrows: V,
1235	) -> MatMut<'_, T, V, Cols> {
1236		self.as_mut().subrows_mut(row_start, nrows)
1237	}
1238
1239	#[inline]
1240	/// see [`MatMut::subcols_mut`]
1241	pub fn subcols_mut<H: Shape>(
1242		&mut self,
1243		col_start: IdxInc<Cols>,
1244		ncols: H,
1245	) -> MatMut<'_, T, Rows, H> {
1246		self.as_mut().subcols_mut(col_start, ncols)
1247	}
1248
1249	#[inline]
1250	#[track_caller]
1251	/// see [`MatMut::as_shape_mut`]
1252	pub fn as_shape_mut<V: Shape, H: Shape>(
1253		&mut self,
1254		nrows: V,
1255		ncols: H,
1256	) -> MatMut<'_, T, V, H> {
1257		self.as_mut().as_shape_mut(nrows, ncols)
1258	}
1259
1260	#[inline]
1261	/// see [`MatMut::as_row_shape_mut`]
1262	pub fn as_row_shape_mut<V: Shape>(
1263		&mut self,
1264		nrows: V,
1265	) -> MatMut<'_, T, V, Cols> {
1266		self.as_mut().as_row_shape_mut(nrows)
1267	}
1268
1269	#[inline]
1270	/// see [`MatMut::as_col_shape_mut`]
1271	pub fn as_col_shape_mut<H: Shape>(
1272		&mut self,
1273		ncols: H,
1274	) -> MatMut<'_, T, Rows, H> {
1275		self.as_mut().as_col_shape_mut(ncols)
1276	}
1277
1278	#[inline]
1279	/// see [`MatMut::as_dyn_stride_mut`]
1280	pub fn as_dyn_stride_mut(
1281		&mut self,
1282	) -> MatMut<'_, T, Rows, Cols, isize, isize> {
1283		self.as_mut().as_dyn_stride_mut()
1284	}
1285
1286	#[inline]
1287	/// see [`MatMut::as_dyn_mut`]
1288	pub fn as_dyn_mut(&mut self) -> MatMut<'_, T, usize, usize> {
1289		self.as_mut().as_dyn_mut()
1290	}
1291
1292	#[inline]
1293	/// see [`MatMut::as_dyn_rows_mut`]
1294	pub fn as_dyn_rows_mut(&mut self) -> MatMut<'_, T, usize, Cols> {
1295		self.as_mut().as_dyn_rows_mut()
1296	}
1297
1298	#[inline]
1299	/// see [`MatMut::as_dyn_cols_mut`]
1300	pub fn as_dyn_cols_mut(&mut self) -> MatMut<'_, T, Rows, usize> {
1301		self.as_mut().as_dyn_cols_mut()
1302	}
1303
1304	#[inline]
1305	/// see [`MatMut::row_mut`]
1306	pub fn row_mut(&mut self, i: Idx<Rows>) -> RowMut<'_, T, Cols> {
1307		self.as_mut().row_mut(i)
1308	}
1309
1310	#[inline]
1311	/// see [`MatMut::col_mut`]
1312	pub fn col_mut(&mut self, j: Idx<Cols>) -> ColMut<'_, T, Rows> {
1313		self.as_mut().col_mut(j)
1314	}
1315
1316	#[inline]
1317	/// see [`MatMut::col_iter_mut`]
1318	pub fn col_iter_mut(
1319		&mut self,
1320	) -> impl '_ + ExactSizeIterator + DoubleEndedIterator<Item = ColMut<'_, T, Rows>>
1321	{
1322		self.as_mut().col_iter_mut()
1323	}
1324
1325	#[inline]
1326	/// see [`MatMut::row_iter_mut`]
1327	pub fn row_iter_mut(
1328		&mut self,
1329	) -> impl '_ + ExactSizeIterator + DoubleEndedIterator<Item = RowMut<'_, T, Cols>>
1330	{
1331		self.as_mut().row_iter_mut()
1332	}
1333
1334	#[inline]
1335	#[track_caller]
1336	#[cfg(feature = "rayon")]
1337	/// see [`MatMut::par_col_iter_mut`]
1338	pub fn par_col_iter_mut(
1339		&mut self,
1340	) -> impl '_ + rayon::iter::IndexedParallelIterator<Item = ColMut<'_, T, Rows>>
1341	where
1342		T: Send,
1343	{
1344		self.as_mut().par_col_iter_mut()
1345	}
1346
1347	#[inline]
1348	#[track_caller]
1349	#[cfg(feature = "rayon")]
1350	/// see [`MatMut::par_row_iter_mut`]
1351	pub fn par_row_iter_mut(
1352		&mut self,
1353	) -> impl '_ + rayon::iter::IndexedParallelIterator<Item = RowMut<'_, T, Cols>>
1354	where
1355		T: Send,
1356	{
1357		self.as_mut().par_row_iter_mut()
1358	}
1359
1360	#[inline]
1361	#[track_caller]
1362	#[cfg(feature = "rayon")]
1363	/// see [`MatMut::par_col_chunks_mut`]
1364	pub fn par_col_chunks_mut(
1365		&mut self,
1366		chunk_size: usize,
1367	) -> impl '_
1368	+ rayon::iter::IndexedParallelIterator<
1369		Item = MatMut<'_, T, Rows, usize>,
1370	>
1371	where
1372		T: Send,
1373	{
1374		self.as_mut().par_col_chunks_mut(chunk_size)
1375	}
1376
1377	#[inline]
1378	#[track_caller]
1379	#[cfg(feature = "rayon")]
1380	/// see [`MatMut::par_col_partition_mut`]
1381	pub fn par_col_partition_mut(
1382		&mut self,
1383		count: usize,
1384	) -> impl '_
1385	+ rayon::iter::IndexedParallelIterator<
1386		Item = MatMut<'_, T, Rows, usize>,
1387	>
1388	where
1389		T: Send,
1390	{
1391		self.as_mut().par_col_partition_mut(count)
1392	}
1393
1394	#[inline]
1395	#[track_caller]
1396	#[cfg(feature = "rayon")]
1397	/// see [`MatMut::par_row_chunks_mut`]
1398	pub fn par_row_chunks_mut(
1399		&mut self,
1400		chunk_size: usize,
1401	) -> impl '_
1402	+ rayon::iter::IndexedParallelIterator<
1403		Item = MatMut<'_, T, usize, Cols>,
1404	>
1405	where
1406		T: Send,
1407	{
1408		self.as_mut().par_row_chunks_mut(chunk_size)
1409	}
1410
1411	#[inline]
1412	#[track_caller]
1413	#[cfg(feature = "rayon")]
1414	/// see [`MatMut::par_row_partition_mut`]
1415	pub fn par_row_partition_mut(
1416		&mut self,
1417		count: usize,
1418	) -> impl '_
1419	+ rayon::iter::IndexedParallelIterator<
1420		Item = MatMut<'_, T, usize, Cols>,
1421	>
1422	where
1423		T: Send,
1424	{
1425		self.as_mut().par_row_partition_mut(count)
1426	}
1427
1428	#[inline]
1429	/// see [`MatMut::split_first_row_mut`]
1430	pub fn split_first_row_mut(
1431		&mut self,
1432	) -> Option<(RowMut<'_, T, Cols>, MatMut<'_, T, usize, Cols>)> {
1433		self.as_mut().split_first_row_mut()
1434	}
1435
1436	#[inline]
1437	/// see [`MatMut::try_as_col_major_mut`]
1438	pub fn try_as_col_major_mut(
1439		&mut self,
1440	) -> Option<MatMut<'_, T, Rows, Cols, ContiguousFwd>> {
1441		self.as_mut().try_as_col_major_mut()
1442	}
1443
1444	#[inline]
1445	/// see [`MatMut::try_as_row_major_mut`]
1446	pub fn try_as_row_major_mut(
1447		&mut self,
1448	) -> Option<MatMut<'_, T, Rows, Cols, isize, ContiguousFwd>> {
1449		self.as_mut().try_as_row_major_mut()
1450	}
1451
1452	#[inline]
1453	#[track_caller]
1454	/// see [`MatMut::two_cols_mut`]
1455	pub fn two_cols_mut(
1456		&mut self,
1457		i0: Idx<Cols>,
1458		i1: Idx<Cols>,
1459	) -> (ColMut<'_, T, Rows>, ColMut<'_, T, Rows>) {
1460		self.as_mut().two_cols_mut(i0, i1)
1461	}
1462
1463	#[inline]
1464	#[track_caller]
1465	/// see [`MatMut::two_rows_mut`]
1466	pub fn two_rows_mut(
1467		&mut self,
1468		i0: Idx<Rows>,
1469		i1: Idx<Rows>,
1470	) -> (RowMut<'_, T, Cols>, RowMut<'_, T, Cols>) {
1471		self.as_mut().two_rows_mut(i0, i1)
1472	}
1473}
1474impl<T, Dim: Shape> Mat<T, Dim, Dim> {
1475	#[inline]
1476	/// see [`MatRef::diagonal`]
1477	pub fn diagonal(&self) -> DiagRef<'_, T, Dim, isize> {
1478		self.as_ref().diagonal()
1479	}
1480
1481	#[inline]
1482	/// see [`MatMut::diagonal_mut`]
1483	pub fn diagonal_mut(&mut self) -> DiagMut<'_, T, Dim, isize> {
1484		self.as_mut().diagonal_mut()
1485	}
1486}
1487impl<'short, T, Rows: Shape, Cols: Shape> Reborrow<'short>
1488	for Own<T, Rows, Cols>
1489{
1490	type Target = Ref<'short, T, Rows, Cols>;
1491
1492	#[inline]
1493	fn rb(&'short self) -> Self::Target {
1494		Ref {
1495			imp: MatView {
1496				ptr: self.raw.ptr,
1497				nrows: self.nrows,
1498				ncols: self.ncols,
1499				row_stride: 1,
1500				col_stride: self.raw.row_capacity as isize,
1501			},
1502			__marker: PhantomData,
1503		}
1504	}
1505}
1506impl<'short, T, Rows: Shape, Cols: Shape> ReborrowMut<'short>
1507	for Own<T, Rows, Cols>
1508{
1509	type Target = Mut<'short, T, Rows, Cols>;
1510
1511	#[inline]
1512	fn rb_mut(&'short mut self) -> Self::Target {
1513		Mut {
1514			imp: MatView {
1515				ptr: self.raw.ptr,
1516				nrows: self.nrows,
1517				ncols: self.ncols,
1518				row_stride: 1,
1519				col_stride: self.raw.row_capacity as isize,
1520			},
1521			__marker: PhantomData,
1522		}
1523	}
1524}
1525impl<T, Cols: Shape> Mat<T, usize, Cols> {
1526	/// inserts a row at the end of the matrix
1527	/// # panics
1528	/// The function panics if the number of columns in the row does not match
1529	/// the number of columns in the matrix
1530	pub fn push_row(&mut self, row: RowRef<'_, T, Cols>)
1531	where
1532		T: Clone,
1533	{
1534		self::assert!(
1535			self.ncols() == row.ncols(),
1536			"row ncols ({:?}) must match matrix ncols ({:?})",
1537			row.ncols(),
1538			self.ncols()
1539		);
1540		self.resize_with(self.nrows() + 1, self.ncols(), |_, j| row[j].clone());
1541	}
1542}
1543impl<T, Rows: Shape> Mat<T, Rows, usize> {
1544	/// inserts a col at the end of the matrix
1545	/// # panics
1546	/// The function panics if the number of rows in the col does not match the
1547	/// number of rows in the matrix
1548	pub fn push_col(&mut self, col: ColRef<'_, T, Rows>)
1549	where
1550		T: Clone,
1551	{
1552		self::assert!(
1553			self.nrows() == col.nrows(),
1554			"col nrows ({:?}) must match matrix nrows ({:?})",
1555			col.nrows(),
1556			self.nrows()
1557		);
1558		self.resize_with(self.nrows(), self.ncols() + 1, |i, _| col[i].clone());
1559	}
1560}
1561impl<T, Rows: Shape, Cols: Shape> Mat<T, Rows, Cols>
1562where
1563	T: RealField,
1564{
1565	/// see [MatRef::min]
1566	pub fn min(self) -> Option<T> {
1567		MatRef::internal_min(self.as_dyn())
1568	}
1569
1570	/// see [MatRef::min]
1571	pub fn max(self) -> Option<T> {
1572		MatRef::internal_max(self.as_dyn())
1573	}
1574}
1575#[cfg(test)]
1576mod tests {
1577	use super::Mat;
1578	use crate::assert;
1579	#[test]
1580	fn test_resize() {
1581		let mut m = mat![
1582			[1.0, 2.0, 3.0],
1583			[4.0, 5.0, 6.0],
1584			[7.0, 8.0, 9.0],
1585			[10.0, 11.0, 12.0],
1586		];
1587		m.resize_with(m.nrows() + 1, m.ncols(), |_, _| 99.9);
1588		let target = mat![
1589			[1.0, 2.0, 3.0],
1590			[4.0, 5.0, 6.0],
1591			[7.0, 8.0, 9.0],
1592			[10.0, 11.0, 12.0],
1593			[99.9, 99.9, 99.9],
1594		];
1595		assert!(m == target);
1596	}
1597	#[test]
1598	fn test_resize_5() {
1599		let mut m = mat![
1600			[1.0, 2.0, 3.0],
1601			[4.0, 5.0, 6.0],
1602			[7.0, 8.0, 9.0],
1603			[10.0, 11.0, 12.0],
1604		];
1605		m.resize_with(m.nrows() + 5, m.ncols(), |_, _| 99.9);
1606		let target = mat![
1607			[1.0, 2.0, 3.0],
1608			[4.0, 5.0, 6.0],
1609			[7.0, 8.0, 9.0],
1610			[10.0, 11.0, 12.0],
1611			[99.9, 99.9, 99.9],
1612			[99.9, 99.9, 99.9],
1613			[99.9, 99.9, 99.9],
1614			[99.9, 99.9, 99.9],
1615			[99.9, 99.9, 99.9],
1616		];
1617		assert!(m == target);
1618	}
1619	#[test]
1620	fn test_resize_5_1() {
1621		let mut m = mat![
1622			[1.0, 2.0, 3.0],
1623			[4.0, 5.0, 6.0],
1624			[7.0, 8.0, 9.0],
1625			[10.0, 11.0, 12.0],
1626		];
1627		m.resize_with(m.nrows() + 5, m.ncols() + 1, |_, _| 99.9);
1628		let target = mat![
1629			[1.0, 2.0, 3.0, 99.9],
1630			[4.0, 5.0, 6.0, 99.9],
1631			[7.0, 8.0, 9.0, 99.9],
1632			[10.0, 11.0, 12.0, 99.9],
1633			[99.9, 99.9, 99.9, 99.9],
1634			[99.9, 99.9, 99.9, 99.9],
1635			[99.9, 99.9, 99.9, 99.9],
1636			[99.9, 99.9, 99.9, 99.9],
1637			[99.9, 99.9, 99.9, 99.9],
1638		];
1639		assert!(m == target);
1640	}
1641	#[test]
1642	fn test_push_row() {
1643		let mut m = mat![[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0],];
1644		let row = row![10.0, 11.0, 12.0];
1645		m.push_row(row.as_ref());
1646		let target = mat![
1647			[1.0, 2.0, 3.0],
1648			[4.0, 5.0, 6.0],
1649			[7.0, 8.0, 9.0],
1650			[10.0, 11.0, 12.0],
1651		];
1652		assert!(m == target);
1653	}
1654	#[test]
1655	#[should_panic]
1656	fn test_push_row_panic() {
1657		let mut m = mat![[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0],];
1658		let row = row![10.0, 11.0, 12.0, 13.0];
1659		m.push_row(row.as_ref());
1660	}
1661	#[test]
1662	fn test_push_col() {
1663		let mut m = mat![[1.0, 2.0, 3.0], [1.0, 2.0, 3.0], [1.0, 2.0, 3.0],];
1664		let col = col![4.0, 4.0, 4.0];
1665		m.push_col(col.as_ref());
1666		let target = mat![
1667			[1.0, 2.0, 3.0, 4.0],
1668			[1.0, 2.0, 3.0, 4.0],
1669			[1.0, 2.0, 3.0, 4.0],
1670		];
1671		assert!(m == target);
1672	}
1673	#[test]
1674	#[should_panic]
1675	fn test_push_col_panic() {
1676		let mut m = mat![[1.0, 2.0, 3.0], [1.0, 2.0, 3.0], [1.0, 2.0, 3.0],];
1677		let col = col![4.0, 4.0, 4.0, 4.0];
1678		m.push_col(col.as_ref());
1679	}
1680	#[test]
1681	fn test_min() {
1682		use crate::Mat;
1683		let m = mat![[1.0, 5.0, 3.0], [4.0, 2.0, 9.0], [7.0, 8.0, 6.0],];
1684		assert_eq!(m.min(), Some(1.0));
1685		let empty: Mat<f64> = Mat::new();
1686		assert_eq!(empty.min(), None);
1687	}
1688	#[test]
1689	fn test_max() {
1690		use crate::Mat;
1691		let m = mat![[1.0, 5.0, 3.0], [4.0, 2.0, 9.0], [7.0, 8.0, 6.0],];
1692		assert_eq!(m.max(), Some(9.0));
1693		let empty: Mat<f64> = Mat::new();
1694		assert_eq!(empty.max(), None);
1695	}
1696
1697	#[test]
1698	fn test_drop() {
1699		use core::cell::Cell;
1700		const M: usize = 5;
1701		const N: usize = 7;
1702
1703		#[derive(Clone)]
1704		struct PanicOnDrop<'a> {
1705			counter: &'a Cell<usize>,
1706		}
1707
1708		impl Drop for PanicOnDrop<'_> {
1709			fn drop(&mut self) {
1710				self.counter.set(self.counter.get() + 1);
1711				if self.counter.get() == M * (N / 2) {
1712					panic!();
1713				}
1714			}
1715		}
1716
1717		let counter = &Cell::new(0);
1718		std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
1719			drop(Mat::full(M, N, PanicOnDrop { counter }))
1720		}))
1721		.unwrap_err();
1722		// matrix elements + init value
1723		assert!(counter.get() == M * N + 1);
1724	}
1725}