use super::*;
use crate::{
assert, debug_assert,
diag::{DiagMut, DiagRef},
iter,
iter::chunks::ChunkPolicy,
linalg::zip,
unzipped, zipped_rw, Idx, IdxInc, Unbind,
};
use core::ops::Range;
#[repr(C)]
pub struct MatMut<'a, E: Entity, R: Shape = usize, C: Shape = usize> {
pub(super) inner: MatImpl<E, R, C>,
pub(super) __marker: PhantomData<&'a E>,
}
impl<E: Entity> Default for MatMut<'_, E> {
#[inline]
fn default() -> Self {
from_column_major_slice_mut_generic(
map!(E, E::UNIT, |(())| &mut [] as &mut [E::Unit]),
0,
0,
)
}
}
impl<'short, E: Entity, R: Shape, C: Shape> Reborrow<'short> for MatMut<'_, E, R, C> {
type Target = MatRef<'short, E, R, C>;
#[inline]
fn rb(&'short self) -> Self::Target {
MatRef {
inner: self.inner,
__marker: PhantomData,
}
}
}
impl<'short, E: Entity, R: Shape, C: Shape> ReborrowMut<'short> for MatMut<'_, E, R, C> {
type Target = MatMut<'short, E, R, C>;
#[inline]
fn rb_mut(&'short mut self) -> Self::Target {
MatMut {
inner: self.inner,
__marker: PhantomData,
}
}
}
impl<'a, E: Entity, R: Shape, C: Shape> IntoConst for MatMut<'a, E, R, C> {
type Target = MatRef<'a, E, R, C>;
#[inline]
fn into_const(self) -> Self::Target {
MatRef {
inner: self.inner,
__marker: PhantomData,
}
}
}
impl<'a, E: Entity, R: Shape, C: Shape> MatMut<'a, E, R, C> {
#[inline]
pub(crate) unsafe fn __from_raw_parts(
ptr: PtrMut<E>,
nrows: R,
ncols: C,
row_stride: isize,
col_stride: isize,
) -> Self {
Self {
inner: MatImpl {
ptr: into_copy::<E, _>(map!(E, ptr, |(ptr)| NonNull::new_unchecked(ptr),)),
nrows,
ncols,
row_stride,
col_stride,
},
__marker: PhantomData,
}
}
#[inline(always)]
pub fn nrows(&self) -> R {
self.inner.nrows
}
#[inline(always)]
pub fn ncols(&self) -> C {
self.inner.ncols
}
#[inline]
pub fn shape(&self) -> (R, C) {
(self.nrows(), self.ncols())
}
#[inline(always)]
pub fn as_ptr(self) -> PtrConst<E> {
self.into_const().as_ptr()
}
#[inline(always)]
pub fn as_ptr_mut(self) -> PtrMut<E> {
map!(E, from_copy::<E, _>(self.inner.ptr), |(ptr)| ptr.as_ptr(),)
}
#[inline(always)]
pub fn row_stride(&self) -> isize {
self.inner.row_stride
}
#[inline(always)]
pub fn col_stride(&self) -> isize {
self.inner.col_stride
}
#[inline(always)]
pub fn ptr_at(self, row: usize, col: usize) -> PtrConst<E> {
self.into_const().ptr_at(row, col)
}
#[inline(always)]
pub fn ptr_at_mut(self, row: usize, col: usize) -> PtrMut<E> {
let offset = ((row as isize).wrapping_mul(self.inner.row_stride))
.wrapping_add((col as isize).wrapping_mul(self.inner.col_stride));
map!(E, self.as_ptr_mut(), |(ptr)| ptr.wrapping_offset(offset),)
}
#[inline(always)]
#[doc(hidden)]
pub unsafe fn ptr_at_unchecked(self, row: usize, col: usize) -> PtrConst<E> {
self.into_const().ptr_at_unchecked(row, col)
}
#[inline(always)]
#[doc(hidden)]
pub unsafe fn ptr_at_mut_unchecked(self, row: usize, col: usize) -> PtrMut<E> {
let offset = crate::utils::unchecked_add(
crate::utils::unchecked_mul(row, self.inner.row_stride),
crate::utils::unchecked_mul(col, self.inner.col_stride),
);
map!(E, self.as_ptr_mut(), |(ptr)| ptr.offset(offset),)
}
#[inline(always)]
#[must_use]
pub fn transpose(self) -> MatRef<'a, E, C, R> {
self.into_const().transpose()
}
#[inline(always)]
#[must_use]
pub fn transpose_mut(self) -> MatMut<'a, E, C, R> {
unsafe {
super::from_raw_parts_mut(
map!(E, from_copy::<E, _>(self.inner.ptr), |(ptr)| ptr.as_ptr(),),
self.ncols(),
self.nrows(),
self.col_stride(),
self.row_stride(),
)
}
}
#[inline(always)]
#[must_use]
pub fn conjugate(self) -> MatRef<'a, E::Conj, R, C>
where
E: Conjugate,
{
self.into_const().conjugate()
}
#[inline(always)]
#[must_use]
pub fn conjugate_mut(self) -> MatMut<'a, E::Conj, R, C>
where
E: Conjugate,
{
unsafe { self.into_const().conjugate().const_cast() }
}
#[inline(always)]
#[must_use]
pub fn adjoint(self) -> MatRef<'a, E::Conj, C, R>
where
E: Conjugate,
{
self.into_const().adjoint()
}
#[inline(always)]
#[must_use]
pub fn adjoint_mut(self) -> MatMut<'a, E::Conj, C, R>
where
E: Conjugate,
{
self.transpose_mut().conjugate_mut()
}
#[inline(always)]
#[must_use]
pub fn canonicalize(self) -> (MatRef<'a, E::Canonical, R, C>, Conj)
where
E: Conjugate,
{
self.into_const().canonicalize()
}
#[inline(always)]
#[must_use]
pub fn canonicalize_mut(self) -> (MatMut<'a, E::Canonical, R, C>, Conj)
where
E: Conjugate,
{
let (canonical, conj) = self.into_const().canonicalize();
unsafe { (canonical.const_cast(), conj) }
}
#[inline]
pub fn as_dyn(self) -> MatRef<'a, E> {
let nrows = self.nrows().unbound();
let ncols = self.ncols().unbound();
let row_stride = self.row_stride();
let col_stride = self.col_stride();
unsafe { from_raw_parts(self.as_ptr(), nrows, ncols, row_stride, col_stride) }
}
#[inline]
pub fn as_dyn_mut(self) -> MatMut<'a, E> {
let nrows = self.nrows().unbound();
let ncols = self.ncols().unbound();
let row_stride = self.row_stride();
let col_stride = self.col_stride();
unsafe { from_raw_parts_mut(self.as_ptr_mut(), nrows, ncols, row_stride, col_stride) }
}
#[inline]
pub fn as_shape<V: Shape, H: Shape>(self, nrows: V, ncols: H) -> MatRef<'a, E, V, H> {
self.into_const().as_shape(nrows, ncols)
}
#[inline]
pub fn as_shape_mut<V: Shape, H: Shape>(self, nrows: V, ncols: H) -> MatMut<'a, E, V, H> {
unsafe { self.into_const().as_shape(nrows, ncols).const_cast() }
}
#[inline(always)]
#[doc(hidden)]
pub unsafe fn overflowing_ptr_at(self, row: IdxInc<R>, col: IdxInc<C>) -> PtrConst<E> {
self.into_const().overflowing_ptr_at(row, col)
}
#[inline(always)]
#[doc(hidden)]
pub unsafe fn overflowing_ptr_at_mut(self, row: IdxInc<R>, col: IdxInc<C>) -> PtrMut<E> {
unsafe {
let cond = (row != self.nrows()) & (col != self.ncols());
let offset = (cond as usize).wrapping_neg() as isize
& (isize::wrapping_add(
(row.unbound() as isize).wrapping_mul(self.inner.row_stride),
(col.unbound() as isize).wrapping_mul(self.inner.col_stride),
));
map!(E, self.as_ptr_mut(), |(ptr)| ptr.offset(offset),)
}
}
#[inline(always)]
#[track_caller]
pub unsafe fn ptr_inbounds_at(self, row: Idx<R>, col: Idx<C>) -> PtrConst<E> {
self.into_const().ptr_inbounds_at(row, col)
}
#[inline(always)]
#[track_caller]
pub unsafe fn ptr_inbounds_at_mut(self, row: Idx<R>, col: Idx<C>) -> PtrMut<E> {
debug_assert!(all(row < self.nrows(), col < self.ncols()));
self.ptr_at_mut_unchecked(row.unbound(), col.unbound())
}
#[track_caller]
#[inline(always)]
#[doc(hidden)]
pub fn try_get_contiguous_col(self, j: Idx<C>) -> Slice<'a, E> {
self.into_const().try_get_contiguous_col(j)
}
#[track_caller]
#[inline(always)]
#[doc(hidden)]
pub fn try_get_contiguous_col_mut(self, j: Idx<C>) -> SliceMut<'a, E> {
assert!(self.row_stride() == 1);
let col = self.col_mut(j);
let m = col.nrows().unbound();
if m == 0 {
map!(E, E::UNIT, |(())| &mut [] as &mut [E::Unit],)
} else {
map!(E, col.as_ptr_mut(), |(ptr)| unsafe {
core::slice::from_raw_parts_mut(ptr, m)
},)
}
}
#[inline(always)]
#[track_caller]
pub unsafe fn split_at_unchecked(
self,
row: IdxInc<R>,
col: IdxInc<C>,
) -> (
MatRef<'a, E, usize, usize>,
MatRef<'a, E, usize, usize>,
MatRef<'a, E, usize, usize>,
MatRef<'a, E, usize, usize>,
) {
self.into_const().split_at_unchecked(row, col)
}
#[inline(always)]
#[track_caller]
pub fn split_at(
self,
row: IdxInc<R>,
col: IdxInc<C>,
) -> (
MatRef<'a, E, usize, usize>,
MatRef<'a, E, usize, usize>,
MatRef<'a, E, usize, usize>,
MatRef<'a, E, usize, usize>,
) {
self.into_const().split_at(row, col)
}
#[inline(always)]
#[track_caller]
pub unsafe fn split_at_mut_unchecked(
self,
row: IdxInc<R>,
col: IdxInc<C>,
) -> (
MatMut<'a, E, usize, usize>,
MatMut<'a, E, usize, usize>,
MatMut<'a, E, usize, usize>,
MatMut<'a, E, usize, usize>,
) {
let (top_left, top_right, bot_left, bot_right) =
self.into_const().split_at_unchecked(row, col);
(
top_left.const_cast(),
top_right.const_cast(),
bot_left.const_cast(),
bot_right.const_cast(),
)
}
#[inline(always)]
#[track_caller]
pub fn split_at_mut(
self,
row: IdxInc<R>,
col: IdxInc<C>,
) -> (
MatMut<'a, E, usize, usize>,
MatMut<'a, E, usize, usize>,
MatMut<'a, E, usize, usize>,
MatMut<'a, E, usize, usize>,
) {
let (top_left, top_right, bot_left, bot_right) = self.into_const().split_at(row, col);
unsafe {
(
top_left.const_cast(),
top_right.const_cast(),
bot_left.const_cast(),
bot_right.const_cast(),
)
}
}
#[inline(always)]
#[track_caller]
pub unsafe fn split_at_row_unchecked(
self,
row: IdxInc<R>,
) -> (MatRef<'a, E, usize, C>, MatRef<'a, E, usize, C>) {
self.into_const().split_at_row_unchecked(row)
}
#[inline(always)]
#[track_caller]
pub fn split_at_row(
self,
row: IdxInc<R>,
) -> (MatRef<'a, E, usize, C>, MatRef<'a, E, usize, C>) {
self.into_const().split_at_row(row)
}
#[inline(always)]
#[track_caller]
pub unsafe fn split_at_row_mut_unchecked(
self,
row: IdxInc<R>,
) -> (MatMut<'a, E, usize, C>, MatMut<'a, E, usize, C>) {
let (top, bot) = self.into_const().split_at_row_unchecked(row);
(top.const_cast(), bot.const_cast())
}
#[inline(always)]
#[track_caller]
pub fn split_at_row_mut(
self,
row: IdxInc<R>,
) -> (MatMut<'a, E, usize, C>, MatMut<'a, E, usize, C>) {
let (top, bot) = self.into_const().split_at_row(row);
unsafe { (top.const_cast(), bot.const_cast()) }
}
#[inline(always)]
#[track_caller]
pub unsafe fn split_at_col_unchecked(
self,
col: IdxInc<C>,
) -> (MatRef<'a, E, R, usize>, MatRef<'a, E, R, usize>) {
self.into_const().split_at_col_unchecked(col)
}
#[inline(always)]
#[track_caller]
pub fn split_at_col(
self,
col: IdxInc<C>,
) -> (MatRef<'a, E, R, usize>, MatRef<'a, E, R, usize>) {
self.into_const().split_at_col(col)
}
#[inline(always)]
#[track_caller]
pub unsafe fn split_at_col_mut_unchecked(
self,
col: IdxInc<C>,
) -> (MatMut<'a, E, R, usize>, MatMut<'a, E, R, usize>) {
let (left, right) = self.into_const().split_at_col_unchecked(col);
(left.const_cast(), right.const_cast())
}
#[inline(always)]
#[track_caller]
pub fn split_at_col_mut(
self,
col: IdxInc<C>,
) -> (MatMut<'a, E, R, usize>, MatMut<'a, E, R, usize>) {
let (left, right) = self.into_const().split_at_col(col);
unsafe { (left.const_cast(), right.const_cast()) }
}
#[inline(always)]
#[track_caller]
pub unsafe fn get_unchecked<RowRange, ColRange>(
self,
row: RowRange,
col: ColRange,
) -> <MatRef<'a, E, R, C> as MatIndex<RowRange, ColRange>>::Target
where
MatRef<'a, E, R, C>: MatIndex<RowRange, ColRange>,
{
self.into_const().get_unchecked(row, col)
}
#[inline(always)]
#[track_caller]
pub fn get<RowRange, ColRange>(
self,
row: RowRange,
col: ColRange,
) -> <MatRef<'a, E, R, C> as MatIndex<RowRange, ColRange>>::Target
where
MatRef<'a, E, R, C>: MatIndex<RowRange, ColRange>,
{
self.into_const().get(row, col)
}
#[inline(always)]
#[track_caller]
pub unsafe fn get_mut_unchecked<RowRange, ColRange>(
self,
row: RowRange,
col: ColRange,
) -> <Self as MatIndex<RowRange, ColRange>>::Target
where
Self: MatIndex<RowRange, ColRange>,
{
<Self as MatIndex<RowRange, ColRange>>::get_unchecked(self, row, col)
}
#[inline(always)]
#[track_caller]
pub fn get_mut<RowRange, ColRange>(
self,
row: RowRange,
col: ColRange,
) -> <Self as MatIndex<RowRange, ColRange>>::Target
where
Self: MatIndex<RowRange, ColRange>,
{
<Self as MatIndex<RowRange, ColRange>>::get(self, row, col)
}
#[inline(always)]
#[track_caller]
pub unsafe fn at_unchecked(self, row: Idx<R>, col: Idx<C>) -> Ref<'a, E> {
unsafe { map!(E, self.ptr_inbounds_at(row, col), |(ptr)| &*ptr) }
}
#[inline(always)]
#[track_caller]
pub fn at(self, row: Idx<R>, col: Idx<C>) -> Ref<'a, E> {
assert!(all(row < self.nrows(), col < self.ncols()));
unsafe { map!(E, self.ptr_inbounds_at(row, col), |(ptr)| &*ptr) }
}
#[inline(always)]
#[track_caller]
pub unsafe fn at_mut_unchecked(self, row: Idx<R>, col: Idx<C>) -> Mut<'a, E> {
unsafe { map!(E, self.ptr_inbounds_at_mut(row, col), |(ptr)| &mut *ptr) }
}
#[inline(always)]
#[track_caller]
pub fn at_mut(self, row: Idx<R>, col: Idx<C>) -> Mut<'a, E> {
assert!(all(row < self.nrows(), col < self.ncols()));
unsafe { map!(E, self.ptr_inbounds_at_mut(row, col), |(ptr)| &mut *ptr) }
}
#[inline(always)]
#[track_caller]
pub unsafe fn read_unchecked(&self, row: Idx<R>, col: Idx<C>) -> E {
self.rb().read_unchecked(row, col)
}
#[inline(always)]
#[track_caller]
pub fn read(&self, row: Idx<R>, col: Idx<C>) -> E {
self.rb().read(row, col)
}
#[inline(always)]
#[track_caller]
pub unsafe fn write_unchecked(&mut self, row: Idx<R>, col: Idx<C>, value: E) {
let units = value.faer_into_units();
let zipped = E::faer_zip(units, (*self).rb_mut().ptr_inbounds_at_mut(row, col));
map!(E, zipped, |((unit, ptr))| *ptr = unit,);
}
#[inline(always)]
#[track_caller]
pub fn write(&mut self, row: Idx<R>, col: Idx<C>, value: E) {
assert!(all(row < self.nrows(), col < self.ncols()));
unsafe { self.write_unchecked(row, col, value) };
}
#[track_caller]
pub fn copy_from_triangular_lower<ViewE: Conjugate<Canonical = E>>(
&mut self,
other: impl AsMatRef<ViewE, R = R, C = C>,
) {
#[track_caller]
#[inline(always)]
fn implementation<R: Shape, C: Shape, E: Entity, ViewE: Conjugate<Canonical = E>>(
this: MatMut<'_, E, R, C>,
other: MatRef<'_, ViewE, R, C>,
) {
zipped_rw!(this, other).for_each_triangular_lower(
zip::Diag::Include,
#[inline(always)]
|unzipped!(mut dst, src)| dst.write(src.read().canonicalize()),
);
}
implementation(self.rb_mut(), other.as_mat_ref())
}
#[track_caller]
pub fn copy_from_strict_triangular_lower<ViewE: Conjugate<Canonical = E>>(
&mut self,
other: impl AsMatRef<ViewE, R = R, C = C>,
) {
#[track_caller]
#[inline(always)]
fn implementation<R: Shape, C: Shape, E: Entity, ViewE: Conjugate<Canonical = E>>(
this: MatMut<'_, E, R, C>,
other: MatRef<'_, ViewE, R, C>,
) {
zipped_rw!(this, other).for_each_triangular_lower(
zip::Diag::Skip,
#[inline(always)]
|unzipped!(mut dst, src)| dst.write(src.read().canonicalize()),
);
}
implementation(self.rb_mut(), other.as_mat_ref())
}
#[track_caller]
#[inline(always)]
pub fn copy_from_triangular_upper<ViewE: Conjugate<Canonical = E>>(
&mut self,
other: impl AsMatRef<ViewE, R = R, C = C>,
) {
(*self)
.rb_mut()
.transpose_mut()
.copy_from_triangular_lower(other.as_mat_ref().transpose())
}
#[track_caller]
#[inline(always)]
pub fn copy_from_strict_triangular_upper<ViewE: Conjugate<Canonical = E>>(
&mut self,
other: impl AsMatRef<ViewE, R = R, C = C>,
) {
(*self)
.rb_mut()
.transpose_mut()
.copy_from_strict_triangular_lower(other.as_mat_ref().transpose())
}
#[track_caller]
pub fn copy_from<ViewE: Conjugate<Canonical = E>>(
&mut self,
other: impl AsMatRef<ViewE, R = R, C = C>,
) {
#[track_caller]
#[inline(always)]
fn implementation<R: Shape, C: Shape, E: Entity, ViewE: Conjugate<Canonical = E>>(
this: MatMut<'_, E, R, C>,
other: MatRef<'_, ViewE, R, C>,
) {
zipped_rw!(this, other)
.for_each(|unzipped!(mut dst, src)| dst.write(src.read().canonicalize()));
}
implementation(self.rb_mut(), other.as_mat_ref())
}
#[track_caller]
pub fn fill_zero(&mut self)
where
E: ComplexField,
{
zipped_rw!(self.rb_mut()).for_each(
#[inline(always)]
|unzipped!(mut x)| x.write(E::faer_zero()),
);
}
#[track_caller]
pub fn fill(&mut self, constant: E) {
zipped_rw!((*self).rb_mut()).for_each(
#[inline(always)]
|unzipped!(mut x)| x.write(constant),
);
}
#[inline(always)]
#[must_use]
pub fn reverse_rows(self) -> MatRef<'a, E, R, C> {
self.into_const().reverse_rows()
}
#[inline(always)]
#[must_use]
pub fn reverse_rows_mut(self) -> Self {
unsafe { self.into_const().reverse_rows().const_cast() }
}
#[inline(always)]
#[must_use]
pub fn reverse_cols(self) -> MatRef<'a, E, R, C> {
self.into_const().reverse_cols()
}
#[inline(always)]
#[must_use]
pub fn reverse_cols_mut(self) -> Self {
unsafe { self.into_const().reverse_cols().const_cast() }
}
#[inline(always)]
#[must_use]
pub fn reverse_rows_and_cols(self) -> MatRef<'a, E, R, C> {
self.into_const().reverse_rows_and_cols()
}
#[inline(always)]
#[must_use]
pub fn reverse_rows_and_cols_mut(self) -> Self {
unsafe { self.into_const().reverse_rows_and_cols().const_cast() }
}
#[track_caller]
#[inline(always)]
pub unsafe fn submatrix_unchecked<V: Shape, H: Shape>(
self,
row_start: IdxInc<R>,
col_start: IdxInc<C>,
nrows: V,
ncols: H,
) -> MatRef<'a, E, V, H> {
self.into_const()
.submatrix_unchecked(row_start, col_start, nrows, ncols)
}
#[track_caller]
#[inline(always)]
pub unsafe fn submatrix_mut_unchecked<V: Shape, H: Shape>(
self,
row_start: IdxInc<R>,
col_start: IdxInc<C>,
nrows: V,
ncols: H,
) -> MatMut<'a, E, V, H> {
self.into_const()
.submatrix_unchecked(row_start, col_start, nrows, ncols)
.const_cast()
}
#[track_caller]
#[inline(always)]
pub fn submatrix<V: Shape, H: Shape>(
self,
row_start: IdxInc<R>,
col_start: IdxInc<C>,
nrows: V,
ncols: H,
) -> MatRef<'a, E, V, H> {
self.into_const()
.submatrix(row_start, col_start, nrows, ncols)
}
#[track_caller]
#[inline(always)]
pub fn submatrix_mut<V: Shape, H: Shape>(
self,
row_start: IdxInc<R>,
col_start: IdxInc<C>,
nrows: V,
ncols: H,
) -> MatMut<'a, E, V, H> {
unsafe {
self.into_const()
.submatrix(row_start, col_start, nrows, ncols)
.const_cast()
}
}
#[track_caller]
#[inline(always)]
pub unsafe fn subrows_unchecked<V: Shape>(
self,
row_start: IdxInc<R>,
nrows: V,
) -> MatRef<'a, E, V, C> {
self.into_const().subrows_unchecked(row_start, nrows)
}
#[track_caller]
#[inline(always)]
pub unsafe fn subrows_mut_unchecked<V: Shape>(
self,
row_start: IdxInc<R>,
nrows: V,
) -> MatMut<'a, E, V, C> {
self.into_const()
.subrows_unchecked(row_start, nrows)
.const_cast()
}
#[track_caller]
#[inline(always)]
pub fn subrows<V: Shape>(self, row_start: IdxInc<R>, nrows: V) -> MatRef<'a, E, V, C> {
self.into_const().subrows(row_start, nrows)
}
#[track_caller]
#[inline(always)]
pub fn subrows_mut<V: Shape>(self, row_start: IdxInc<R>, nrows: V) -> MatMut<'a, E, V, C> {
unsafe { self.into_const().subrows(row_start, nrows).const_cast() }
}
#[track_caller]
#[inline(always)]
pub unsafe fn subcols_unchecked<H: Shape>(
self,
col_start: IdxInc<C>,
ncols: H,
) -> MatRef<'a, E, R, H> {
self.into_const().subcols_unchecked(col_start, ncols)
}
#[track_caller]
#[inline(always)]
pub unsafe fn subcols_mut_unchecked<H: Shape>(
self,
col_start: IdxInc<C>,
ncols: H,
) -> MatMut<'a, E, R, H> {
self.into_const()
.subcols_unchecked(col_start, ncols)
.const_cast()
}
#[track_caller]
#[inline(always)]
pub fn subcols<H: Shape>(self, col_start: IdxInc<C>, ncols: H) -> MatRef<'a, E, R, H> {
self.into_const().subcols(col_start, ncols)
}
#[track_caller]
#[inline(always)]
pub fn subcols_mut<H: Shape>(self, col_start: IdxInc<C>, ncols: H) -> MatMut<'a, E, R, H> {
unsafe { self.into_const().subcols(col_start, ncols).const_cast() }
}
#[track_caller]
#[inline(always)]
#[doc(hidden)]
pub fn subcols_range(self, cols: Range<IdxInc<C>>) -> MatRef<'a, E, R, usize> {
self.into_const().subcols_range(cols)
}
#[track_caller]
#[inline(always)]
#[doc(hidden)]
pub fn subcols_range_mut(self, cols: Range<IdxInc<C>>) -> MatMut<'a, E, R, usize> {
unsafe { self.into_const().subcols_range(cols).const_cast() }
}
#[track_caller]
#[inline(always)]
pub unsafe fn row_unchecked(self, row_idx: Idx<R>) -> RowRef<'a, E, C> {
self.into_const().row_unchecked(row_idx)
}
#[track_caller]
#[inline(always)]
pub unsafe fn row_mut_unchecked(self, row_idx: Idx<R>) -> RowMut<'a, E, C> {
self.into_const().row_unchecked(row_idx).const_cast()
}
#[track_caller]
#[inline(always)]
pub fn row(self, row_idx: Idx<R>) -> RowRef<'a, E, C> {
self.into_const().row(row_idx)
}
#[track_caller]
#[inline(always)]
pub fn row_mut(self, row_idx: Idx<R>) -> RowMut<'a, E, C> {
unsafe { self.into_const().row(row_idx).const_cast() }
}
#[track_caller]
#[inline(always)]
pub fn two_rows_mut(
self,
row_idx0: Idx<R>,
row_idx1: Idx<R>,
) -> (RowMut<'a, E, C>, RowMut<'a, E, C>) {
assert!(row_idx0 != row_idx1);
let this = self.into_const();
unsafe {
(
this.row(row_idx0).const_cast(),
this.row(row_idx1).const_cast(),
)
}
}
#[track_caller]
#[inline(always)]
pub unsafe fn col_unchecked(self, col_idx: Idx<C>) -> ColRef<'a, E, R> {
self.into_const().col_unchecked(col_idx)
}
#[track_caller]
#[inline(always)]
pub unsafe fn col_mut_unchecked(self, col_idx: Idx<C>) -> ColMut<'a, E, R> {
self.into_const().col_unchecked(col_idx).const_cast()
}
#[track_caller]
#[inline(always)]
pub fn col(self, col_idx: Idx<C>) -> ColRef<'a, E, R> {
self.into_const().col(col_idx)
}
#[track_caller]
#[inline(always)]
pub fn col_mut(self, col_idx: Idx<C>) -> ColMut<'a, E, R> {
unsafe { self.into_const().col(col_idx).const_cast() }
}
#[track_caller]
#[inline(always)]
pub fn two_cols_mut(
self,
col_idx0: Idx<C>,
col_idx1: Idx<C>,
) -> (ColMut<'a, E, R>, ColMut<'a, E, R>) {
assert!(col_idx0 != col_idx1);
let this = self.into_const();
unsafe {
(
this.col(col_idx0).const_cast(),
this.col(col_idx1).const_cast(),
)
}
}
#[inline]
pub fn to_owned(&self) -> Mat<E::Canonical>
where
E: Conjugate,
{
self.rb().to_owned()
}
#[inline]
pub fn has_nan(&self) -> bool
where
E: ComplexField,
{
self.rb().has_nan()
}
#[inline]
pub fn is_all_finite(&self) -> bool
where
E: ComplexField,
{
self.rb().is_all_finite()
}
#[inline]
pub fn norm_max(&self) -> E::Real
where
E: ComplexField,
{
self.rb().norm_max()
}
#[inline]
pub fn norm_l1(&self) -> E::Real
where
E: ComplexField,
{
self.rb().norm_l1()
}
#[inline]
pub fn norm_l2(&self) -> E::Real
where
E: ComplexField,
{
self.rb().norm_l2()
}
#[inline]
pub fn squared_norm_l2(&self) -> E::Real
where
E: ComplexField,
{
self.rb().squared_norm_l2()
}
#[inline]
pub fn sum(&self) -> E
where
E: ComplexField,
{
self.rb().sum()
}
#[inline]
#[track_caller]
pub fn kron(&self, rhs: impl As2D<E>) -> Mat<E>
where
E: ComplexField,
{
self.rb().kron(rhs)
}
#[inline]
pub fn as_ref(&self) -> MatRef<'_, E, R, C> {
self.rb()
}
#[inline]
pub fn as_mut(&mut self) -> MatMut<'_, E, R, C> {
self.rb_mut()
}
#[inline]
pub fn split_first_col(self) -> Option<(ColRef<'a, E, R>, MatRef<'a, E, R, usize>)> {
self.into_const().split_first_col()
}
#[inline]
pub fn split_last_col(self) -> Option<(ColRef<'a, E, R>, MatRef<'a, E, R, usize>)> {
self.into_const().split_last_col()
}
#[inline]
pub fn split_first_row(self) -> Option<(RowRef<'a, E, C>, MatRef<'a, E, usize, C>)> {
self.into_const().split_first_row()
}
#[inline]
pub fn split_last_row(self) -> Option<(RowRef<'a, E, C>, MatRef<'a, E, usize, C>)> {
self.into_const().split_last_row()
}
#[inline]
pub fn split_first_col_mut(self) -> Option<(ColMut<'a, E, R>, MatMut<'a, E, R, usize>)> {
self.split_first_col()
.map(|(head, tail)| unsafe { (head.const_cast(), tail.const_cast()) })
}
#[inline]
pub fn split_last_col_mut(self) -> Option<(ColMut<'a, E, R>, MatMut<'a, E, R, usize>)> {
self.split_last_col()
.map(|(head, tail)| unsafe { (head.const_cast(), tail.const_cast()) })
}
#[inline]
pub fn split_first_row_mut(self) -> Option<(RowMut<'a, E, C>, MatMut<'a, E, usize, C>)> {
self.split_first_row()
.map(|(head, tail)| unsafe { (head.const_cast(), tail.const_cast()) })
}
#[inline]
pub fn split_last_row_mut(self) -> Option<(RowMut<'a, E, C>, MatMut<'a, E, usize, C>)> {
self.split_last_row()
.map(|(head, tail)| unsafe { (head.const_cast(), tail.const_cast()) })
}
#[inline]
pub fn col_iter(self) -> iter::ColIter<'a, E, R> {
self.into_const().col_iter()
}
#[inline]
pub fn row_iter(self) -> iter::RowIter<'a, E> {
self.into_const().row_iter()
}
#[inline]
pub fn col_iter_mut(self) -> iter::ColIterMut<'a, E, R> {
let nrows = self.nrows();
let ncols = self.ncols();
iter::ColIterMut {
inner: self.as_shape_mut(nrows, ncols.unbound()),
}
}
#[inline]
pub fn row_iter_mut(self) -> iter::RowIterMut<'a, E> {
iter::RowIterMut {
inner: self.as_dyn_mut(),
}
}
#[doc(hidden)]
#[inline(always)]
pub unsafe fn const_cast(self) -> MatMut<'a, E, R, C> {
self
}
#[inline]
#[track_caller]
pub fn col_chunks(self, chunk_size: usize) -> iter::ColChunks<'a, E> {
self.into_const().col_chunks(chunk_size)
}
#[inline]
#[track_caller]
pub fn col_partition(self, count: usize) -> iter::ColPartition<'a, E> {
self.into_const().col_partition(count)
}
#[inline]
#[track_caller]
pub fn row_chunks(self, chunk_size: usize) -> iter::RowChunks<'a, E> {
self.into_const().row_chunks(chunk_size)
}
#[inline]
#[track_caller]
pub fn row_partition(self, count: usize) -> iter::RowPartition<'a, E> {
self.into_const().row_partition(count)
}
#[inline]
#[track_caller]
pub fn col_chunks_mut(self, chunk_size: usize) -> iter::ColChunksMut<'a, E> {
assert!(chunk_size > 0);
let ncols = self.ncols().unbound();
iter::ColChunksMut {
inner: self.as_dyn_mut(),
policy: iter::chunks::ChunkSizePolicy::new(ncols, iter::chunks::ChunkSize(chunk_size)),
}
}
#[inline]
#[track_caller]
pub fn col_partition_mut(self, count: usize) -> iter::ColPartitionMut<'a, E> {
assert!(count > 0);
let ncols = self.ncols().unbound();
iter::ColPartitionMut {
inner: self.as_dyn_mut(),
policy: iter::chunks::PartitionCountPolicy::new(
ncols,
iter::chunks::PartitionCount(count),
),
}
}
#[inline]
#[track_caller]
pub fn row_chunks_mut(self, chunk_size: usize) -> iter::RowChunksMut<'a, E> {
assert!(chunk_size > 0);
let nrows = self.nrows().unbound();
iter::RowChunksMut {
inner: self.as_dyn_mut(),
policy: iter::chunks::ChunkSizePolicy::new(nrows, iter::chunks::ChunkSize(chunk_size)),
}
}
#[inline]
#[track_caller]
pub fn row_partition_mut(self, count: usize) -> iter::RowPartitionMut<'a, E> {
assert!(count > 0);
let nrows = self.nrows().unbound();
iter::RowPartitionMut {
inner: self.as_dyn_mut(),
policy: iter::chunks::PartitionCountPolicy::new(
nrows,
iter::chunks::PartitionCount(count),
),
}
}
#[cfg(feature = "rayon")]
#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
#[inline]
#[track_caller]
pub fn par_col_chunks(
self,
chunk_size: usize,
) -> impl 'a + rayon::iter::IndexedParallelIterator<Item = MatRef<'a, E, R, usize>> {
self.into_const().par_col_chunks(chunk_size)
}
#[cfg(feature = "rayon")]
#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
#[inline]
#[track_caller]
pub fn par_col_partition(
self,
count: usize,
) -> impl 'a + rayon::iter::IndexedParallelIterator<Item = MatRef<'a, E, R, usize>> {
self.into_const().par_col_partition(count)
}
#[cfg(feature = "rayon")]
#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
#[inline]
#[track_caller]
pub fn par_row_chunks(
self,
chunk_size: usize,
) -> impl 'a + rayon::iter::IndexedParallelIterator<Item = MatRef<'a, E, usize, C>> {
self.into_const().par_row_chunks(chunk_size)
}
#[cfg(feature = "rayon")]
#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
#[inline]
#[track_caller]
pub fn par_row_partition(
self,
count: usize,
) -> impl 'a + rayon::iter::IndexedParallelIterator<Item = MatRef<'a, E, usize, C>> {
self.into_const().par_row_partition(count)
}
#[cfg(feature = "rayon")]
#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
#[inline]
#[track_caller]
pub fn par_col_chunks_mut(
self,
chunk_size: usize,
) -> impl 'a + rayon::iter::IndexedParallelIterator<Item = MatMut<'a, E, R, usize>> {
use rayon::prelude::*;
self.into_const()
.par_col_chunks(chunk_size)
.map(|chunk| unsafe { chunk.const_cast() })
}
#[cfg(feature = "rayon")]
#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
#[inline]
#[track_caller]
pub fn par_col_partition_mut(
self,
count: usize,
) -> impl 'a + rayon::iter::IndexedParallelIterator<Item = MatMut<'a, E, R, usize>> {
use rayon::prelude::*;
self.into_const()
.par_col_partition(count)
.map(|x| unsafe { x.const_cast() })
}
#[cfg(feature = "rayon")]
#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
#[inline]
#[track_caller]
pub fn par_row_chunks_mut(
self,
chunk_size: usize,
) -> impl 'a + rayon::iter::IndexedParallelIterator<Item = MatMut<'a, E, usize, C>> {
use rayon::prelude::*;
self.into_const()
.par_row_chunks(chunk_size)
.map(|chunk| unsafe { chunk.const_cast() })
}
#[cfg(feature = "rayon")]
#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
#[inline]
#[track_caller]
pub fn par_row_partition_mut(
self,
count: usize,
) -> impl 'a + rayon::iter::IndexedParallelIterator<Item = MatMut<'a, E, usize, C>> {
use rayon::prelude::*;
self.into_const()
.par_row_partition(count)
.map(|x| unsafe { x.const_cast() })
}
#[track_caller]
#[inline(always)]
pub fn column_vector_as_diagonal(self) -> DiagRef<'a, E, R> {
self.into_const().column_vector_as_diagonal()
}
#[track_caller]
#[inline(always)]
pub fn column_vector_as_diagonal_mut(self) -> DiagMut<'a, E, R> {
assert!(self.ncols().unbound() == 1);
DiagMut {
inner: self.col_mut(unsafe { Idx::<C>::new_unbound(0) }),
}
}
}
impl<'a, E: Entity, N: Shape> MatMut<'a, E, N, N> {
#[inline(always)]
pub fn diagonal(self) -> DiagRef<'a, E, N> {
self.into_const().diagonal()
}
#[inline(always)]
pub fn diagonal_mut(self) -> DiagMut<'a, E, N> {
let size = self.nrows().min(self.ncols());
let row_stride = self.row_stride();
let col_stride = self.col_stride();
unsafe {
DiagMut {
inner: crate::col::from_raw_parts_mut(
self.as_ptr_mut(),
size,
row_stride + col_stride,
),
}
}
}
}
impl<'a, E: RealField, R: Shape, C: Shape> MatMut<'a, num_complex::Complex<E>, R, C> {
#[inline(always)]
pub fn real_imag(self) -> num_complex::Complex<MatRef<'a, E, R, C>> {
self.into_const().real_imag()
}
#[inline(always)]
pub fn real_imag_mut(self) -> num_complex::Complex<MatMut<'a, E, R, C>> {
let num_complex::Complex { re, im } = self.into_const().real_imag();
unsafe {
num_complex::Complex {
re: re.const_cast(),
im: im.const_cast(),
}
}
}
}
impl<E: Entity, R: Shape, C: Shape> AsMatRef<E> for MatMut<'_, E, R, C> {
type R = R;
type C = C;
#[inline]
fn as_mat_ref(&self) -> MatRef<'_, E, R, C> {
(*self).rb()
}
}
impl<E: Entity, R: Shape, C: Shape> AsMatMut<E> for MatMut<'_, E, R, C> {
#[inline]
fn as_mat_mut(&mut self) -> MatMut<'_, E, R, C> {
(*self).rb_mut()
}
}
impl<E: Entity, R: Shape, C: Shape> As2D<E> for MatMut<'_, E, R, C> {
#[inline]
fn as_2d_ref(&self) -> MatRef<'_, E> {
(*self).rb().as_dyn()
}
}
impl<E: Entity, R: Shape, C: Shape> As2DMut<E> for MatMut<'_, E, R, C> {
#[inline]
fn as_2d_mut(&mut self) -> MatMut<'_, E> {
(*self).rb_mut().as_dyn_mut()
}
}
#[inline(always)]
pub unsafe fn from_raw_parts_mut<'a, E: Entity, R: Shape, C: Shape>(
ptr: PtrMut<E>,
nrows: R,
ncols: C,
row_stride: isize,
col_stride: isize,
) -> MatMut<'a, E, R, C> {
MatMut::__from_raw_parts(ptr, nrows, ncols, row_stride, col_stride)
}
#[track_caller]
pub fn from_column_major_slice_mut_generic<E: Entity, R: Shape, C: Shape>(
slice: SliceMut<'_, E>,
nrows: R,
ncols: C,
) -> MatMut<'_, E, R, C> {
from_slice_assert(
nrows.unbound(),
ncols.unbound(),
SliceGroup::<'_, E>::new(E::faer_rb(E::faer_as_ref(&slice))).len(),
);
unsafe {
from_raw_parts_mut(
map!(E, slice, |(slice)| slice.as_mut_ptr(),),
nrows,
ncols,
1,
nrows.unbound() as isize,
)
}
}
#[inline(always)]
#[track_caller]
pub fn from_row_major_slice_mut_generic<E: Entity, R: Shape, C: Shape>(
slice: SliceMut<'_, E>,
nrows: R,
ncols: C,
) -> MatMut<'_, E, R, C> {
from_column_major_slice_mut_generic(slice, ncols, nrows).transpose_mut()
}
#[track_caller]
pub fn from_column_major_slice_with_stride_mut_generic<E: Entity, R: Shape, C: Shape>(
slice: SliceMut<'_, E>,
nrows: R,
ncols: C,
col_stride: usize,
) -> MatMut<'_, E, R, C> {
from_strided_column_major_slice_mut_assert(
nrows.unbound(),
ncols.unbound(),
col_stride,
SliceGroup::<'_, E>::new(E::faer_rb(E::faer_as_ref(&slice))).len(),
);
unsafe {
from_raw_parts_mut(
map!(E, slice, |(slice)| slice.as_mut_ptr(),),
nrows,
ncols,
1,
col_stride as isize,
)
}
}
#[track_caller]
pub fn from_row_major_slice_with_stride_mut_generic<E: Entity, R: Shape, C: Shape>(
slice: SliceMut<'_, E>,
nrows: R,
ncols: C,
row_stride: usize,
) -> MatMut<'_, E, R, C> {
from_column_major_slice_with_stride_mut_generic(slice, ncols, nrows, row_stride).transpose_mut()
}
#[track_caller]
pub fn from_column_major_slice_mut<E: SimpleEntity, R: Shape, C: Shape>(
slice: &mut [E],
nrows: R,
ncols: C,
) -> MatMut<'_, E, R, C> {
from_column_major_slice_mut_generic(slice, nrows, ncols)
}
#[inline(always)]
#[track_caller]
pub fn from_row_major_slice_mut<E: SimpleEntity, R: Shape, C: Shape>(
slice: &mut [E],
nrows: R,
ncols: C,
) -> MatMut<'_, E, R, C> {
from_row_major_slice_mut_generic(slice, nrows, ncols)
}
#[track_caller]
pub fn from_column_major_slice_with_stride_mut<E: SimpleEntity, R: Shape, C: Shape>(
slice: &mut [E],
nrows: R,
ncols: C,
col_stride: usize,
) -> MatMut<'_, E, R, C> {
from_column_major_slice_with_stride_mut_generic(slice, nrows, ncols, col_stride)
}
#[track_caller]
pub fn from_row_major_slice_with_stride_mut<E: SimpleEntity, R: Shape, C: Shape>(
slice: &mut [E],
nrows: R,
ncols: C,
row_stride: usize,
) -> MatMut<'_, E, R, C> {
from_row_major_slice_with_stride_mut_generic(slice, nrows, ncols, row_stride)
}
impl<'a, E: Entity, R: Shape, C: Shape> core::fmt::Debug for MatMut<'a, E, R, C> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.rb().fmt(f)
}
}
impl<E: SimpleEntity> core::ops::Index<(usize, usize)> for MatMut<'_, E> {
type Output = E;
#[inline]
#[track_caller]
fn index(&self, (row, col): (usize, usize)) -> &E {
(*self).rb().get(row, col)
}
}
impl<E: SimpleEntity> core::ops::IndexMut<(usize, usize)> for MatMut<'_, E> {
#[inline]
#[track_caller]
fn index_mut(&mut self, (row, col): (usize, usize)) -> &mut E {
(*self).rb_mut().get_mut(row, col)
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl<E: Entity> matrixcompare_core::Matrix<E> for MatMut<'_, E> {
#[inline]
fn rows(&self) -> usize {
self.nrows()
}
#[inline]
fn cols(&self) -> usize {
self.ncols()
}
#[inline]
fn access(&self) -> matrixcompare_core::Access<'_, E> {
matrixcompare_core::Access::Dense(self)
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl<E: Entity> matrixcompare_core::DenseAccess<E> for MatMut<'_, E> {
#[inline]
fn fetch_single(&self, row: usize, col: usize) -> E {
self.read(row, col)
}
}
impl<E: Conjugate> ColBatch<E> for MatMut<'_, E> {
type Owned = Mat<E::Canonical>;
#[inline]
#[track_caller]
fn new_owned_zeros(nrows: usize, ncols: usize) -> Self::Owned {
Mat::zeros(nrows, ncols)
}
#[inline]
fn new_owned_copied(src: &Self) -> Self::Owned {
src.to_owned()
}
#[inline]
#[track_caller]
fn resize_owned(owned: &mut Self::Owned, nrows: usize, ncols: usize) {
<Self::Owned as ColBatch<E::Canonical>>::resize_owned(owned, nrows, ncols)
}
}
impl<E: Conjugate> ColBatchMut<E> for MatMut<'_, E> {}
impl<E: Conjugate> RowBatch<E> for MatMut<'_, E> {
type Owned = Mat<E::Canonical>;
#[inline]
#[track_caller]
fn new_owned_zeros(nrows: usize, ncols: usize) -> Self::Owned {
Mat::zeros(nrows, ncols)
}
#[inline]
fn new_owned_copied(src: &Self) -> Self::Owned {
src.to_owned()
}
#[inline]
#[track_caller]
fn resize_owned(owned: &mut Self::Owned, nrows: usize, ncols: usize) {
<Self::Owned as RowBatch<E::Canonical>>::resize_owned(owned, nrows, ncols)
}
}
impl<E: Conjugate> RowBatchMut<E> for MatMut<'_, E> {}
pub fn from_mut<E: SimpleEntity>(value: &mut E) -> MatMut<'_, E> {
from_mut_generic(value)
}
pub fn from_mut_generic<E: Entity>(value: Mut<'_, E>) -> MatMut<'_, E> {
unsafe { from_raw_parts_mut(map!(E, value, |(ptr)| ptr as *mut E::Unit), 1, 1, 0, 0) }
}