use crate::internal_prelude::*;
use crate::{Scale, assert, col, diag, get_global_parallelism, mat, perm, row};
use core::ops::{
Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign,
};
extern crate alloc;
macro_rules! impl_binop {
(
{ $(impl <$($ty_param:ident $(: $bound:tt)?),* $(,)?> $trait:ident <$rhs:ty > for
$lhs:ty { type Output = $out:ty; fn $name:ident ($self:ident, $rhs_:ident : _
$(,)?) $block:block })* }
) => {
$(impl <$($ty_param $(: $bound)?,)*> $trait <&$rhs > for &$lhs { type Output =
$out; #[track_caller] fn $name ($self, $rhs_ : &$rhs) -> Self::Output $block }
impl <$($ty_param $(: $bound)?,)*> $trait <$rhs > for $lhs { type Output = $out;
#[track_caller] fn $name ($self, $rhs_ : $rhs) -> Self::Output { $trait ::$name
(&$self, &$rhs_) } } impl <$($ty_param $(: $bound)?,)*> $trait <$rhs > for &$lhs
{ type Output = $out; #[track_caller] fn $name ($self, $rhs_ : $rhs) ->
Self::Output { $trait ::$name ($self, &$rhs_) } } impl <$($ty_param $(:
$bound)?,)*> $trait <&$rhs > for $lhs { type Output = $out; #[track_caller] fn
$name ($self, $rhs_ : &$rhs) -> Self::Output { $trait ::$name (&$self, $rhs_) }
})*
};
}
macro_rules! impl_op {
(
{ $(impl <$($ty_param:ident $(: $bound:tt)?),* $(,)?> $trait:ident for $lhs:ty {
type Output = $out:ty; fn $name:ident ($self:ident $(,)?) $block:block })* }
) => {
$(impl <$($ty_param $(: $bound)?,)*> $trait for &$lhs { type Output = $out;
#[track_caller] fn $name ($self) -> Self::Output $block } impl <$($ty_param $(:
$bound)?,)*> $trait for $lhs { type Output = $out; #[track_caller] fn $name
($self) -> Self::Output { $trait ::$name (&$self) } })*
};
}
macro_rules! impl_op_assign {
(
{ $(impl <$($ty_param:ident $(: $bound:tt)?),* $(,)?> $trait:ident <$rhs:ty > for
$lhs:ty { fn $name:ident (& mut $self:ident, $rhs_:ident : _ $(,)?) $block:block
})* }
) => {
$(impl <$($ty_param $(: $bound)?,)*> $trait <&$rhs > for $lhs { #[track_caller]
fn $name (& mut $self, $rhs_ : &$rhs) $block } impl <$($ty_param $(: $bound)?,)*>
$trait <$rhs > for $lhs { #[track_caller] fn $name (& mut $self, $rhs_ : $rhs) {
$trait ::$name ($self, &$rhs_) } })*
};
}
impl<
LT: PartialEq<RT>,
LRows: Shape,
LCols: Shape,
LRStride: Stride,
LCStride: Stride,
RT,
RRows: Shape,
RCols: Shape,
RRStride: Stride,
RCStride: Stride,
L: for<'a> Reborrow<
'a,
Target = mat::Ref<'a, LT, LRows, LCols, LRStride, LCStride>,
>,
R: for<'a> Reborrow<
'a,
Target = mat::Ref<'a, RT, RRows, RCols, RRStride, RCStride>,
>,
> PartialEq<mat::generic::Mat<R>> for mat::generic::Mat<L>
{
fn eq(&self, other: &mat::generic::Mat<R>) -> bool {
fn imp<LT: PartialEq<RT>, RT>(
l: MatRef<'_, LT>,
r: MatRef<'_, RT>,
) -> bool {
if l.nrows() != r.nrows() {
return false;
}
with_dim!(M, l.nrows());
with_dim!(N, l.ncols());
let l = l.as_shape(M, N);
let r = r.as_shape(M, N);
for j in N.indices() {
for i in M.indices() {
if l[(i, j)] != r[(i, j)] {
return false;
}
}
}
true
}
imp(
self.rb().as_dyn().as_dyn_stride(),
other.rb().as_dyn().as_dyn_stride(),
)
}
}
impl<
LT: PartialEq<RT>,
LRows: Shape,
LRStride: Stride,
RT,
RRows: Shape,
RRStride: Stride,
L: for<'a> Reborrow<'a, Target = col::Ref<'a, LT, LRows, LRStride>>,
R: for<'a> Reborrow<'a, Target = col::Ref<'a, RT, RRows, RRStride>>,
> PartialEq<col::generic::Col<R>> for col::generic::Col<L>
{
fn eq(&self, other: &col::generic::Col<R>) -> bool {
fn imp<LT: PartialEq<RT>, RT>(
l: ColRef<'_, LT>,
r: ColRef<'_, RT>,
) -> bool {
if l.nrows() != r.nrows() {
return false;
}
with_dim!(N, l.nrows());
let l = l.as_row_shape(N);
let r = r.as_row_shape(N);
for i in N.indices() {
if l[i] != r[i] {
return false;
}
}
true
}
imp(
self.rb().as_dyn_rows().as_dyn_stride(),
other.rb().as_dyn_rows().as_dyn_stride(),
)
}
}
impl<
LT: PartialEq<RT>,
LCols: Shape,
LCStride: Stride,
RT,
RCols: Shape,
RCStride: Stride,
L: for<'a> Reborrow<'a, Target = row::Ref<'a, LT, LCols, LCStride>>,
R: for<'a> Reborrow<'a, Target = row::Ref<'a, RT, RCols, RCStride>>,
> PartialEq<row::generic::Row<R>> for row::generic::Row<L>
{
fn eq(&self, other: &row::generic::Row<R>) -> bool {
self.rb().transpose() == other.rb().transpose()
}
}
impl<
LT: PartialEq<RT>,
LDim: Shape,
LStride: Stride,
RT,
RDim: Shape,
RStride: Stride,
L: for<'a> Reborrow<'a, Target = diag::Ref<'a, LT, LDim, LStride>>,
R: for<'a> Reborrow<'a, Target = diag::Ref<'a, RT, RDim, RStride>>,
> PartialEq<diag::generic::Diag<R>> for diag::generic::Diag<L>
{
fn eq(&self, other: &diag::generic::Diag<R>) -> bool {
self.rb().column_vector() == other.rb().column_vector()
}
}
impl<
LI: Index,
LN: Shape,
RI: Index,
RN: Shape,
L: for<'a> Reborrow<'a, Target = perm::Ref<'a, LI, LN>>,
R: for<'a> Reborrow<'a, Target = perm::Ref<'a, RI, RN>>,
> PartialEq<perm::generic::Perm<R>> for perm::generic::Perm<L>
where
LN::Idx<LI>: PartialEq<RN::Idx<RI>>,
{
#[inline]
fn eq(&self, other: &perm::generic::Perm<R>) -> bool {
self.rb().arrays().0 == other.rb().arrays().0
}
}
impl_op_assign!({
impl<
T: ComplexField,
Rows: Shape,
Cols: Shape,
LRStride: Stride,
LCStride: Stride,
RT: (Conjugate<Canonical = T>),
RRStride: Stride,
RCStride: Stride,
L: (for<'a> ReborrowMut<
'a,
Target = mat::Mut<'a, T, Rows, Cols, LRStride, LCStride>,
>),
R: (for<'a> Reborrow<
'a,
Target = mat::Ref<'a, RT, Rows, Cols, RRStride, RCStride>,
>),
> SubAssign<mat::generic::Mat<R>> for mat::generic::Mat<L>
{
fn sub_assign(&mut self, rhs: _) {
fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
lhs: MatMut<'_, T>,
rhs: MatRef<'_, RT>,
) {
zip!(lhs, rhs).for_each(sub_assign_fn::<T, RT>())
}
let lhs = self.rb_mut();
imp(
lhs.as_dyn_mut().as_dyn_stride_mut(),
rhs.rb().as_dyn().as_dyn_stride(),
);
}
}
impl<
T: ComplexField,
Rows: Shape,
LRStride: Stride,
RT: (Conjugate<Canonical = T>),
RRStride: Stride,
L: (for<'a> ReborrowMut<'a, Target = col::Mut<'a, T, Rows, LRStride>>),
R: (for<'a> Reborrow<'a, Target = col::Ref<'a, RT, Rows, RRStride>>),
> SubAssign<col::generic::Col<R>> for col::generic::Col<L>
{
fn sub_assign(&mut self, rhs: _) {
fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
lhs: ColMut<'_, T>,
rhs: ColRef<'_, RT>,
) {
zip!(lhs, rhs).for_each(sub_assign_fn::<T, RT>())
}
let lhs = self.rb_mut();
imp(
lhs.as_dyn_rows_mut().as_dyn_stride_mut(),
rhs.rb().as_dyn_rows().as_dyn_stride(),
);
}
}
impl<
T: ComplexField,
Cols: Shape,
LCStride: Stride,
RT: (Conjugate<Canonical = T>),
RCStride: Stride,
L: (for<'a> ReborrowMut<'a, Target = row::Mut<'a, T, Cols, LCStride>>),
R: (for<'a> Reborrow<'a, Target = row::Ref<'a, RT, Cols, RCStride>>),
> SubAssign<row::generic::Row<R>> for row::generic::Row<L>
{
fn sub_assign(&mut self, rhs: _) {
fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
lhs: RowMut<'_, T>,
rhs: RowRef<'_, RT>,
) {
SubAssign::sub_assign(
&mut lhs.transpose_mut(),
&rhs.transpose(),
)
}
let lhs = self.rb_mut();
imp(
lhs.as_dyn_cols_mut().as_dyn_stride_mut(),
rhs.rb().as_dyn_cols().as_dyn_stride(),
);
}
}
impl<
T: ComplexField,
Dim: Shape,
LStride: Stride,
RT: (Conjugate<Canonical = T>),
RStride: Stride,
L: (for<'a> ReborrowMut<'a, Target = diag::Mut<'a, T, Dim, LStride>>),
R: (for<'a> Reborrow<'a, Target = diag::Ref<'a, RT, Dim, RStride>>),
> SubAssign<diag::generic::Diag<R>> for diag::generic::Diag<L>
{
fn sub_assign(&mut self, rhs: _) {
fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
lhs: ColMut<'_, T>,
rhs: ColRef<'_, RT>,
) {
SubAssign::sub_assign(&mut { lhs }, &rhs)
}
let lhs = self.rb_mut();
imp(
lhs.column_vector_mut()
.as_dyn_rows_mut()
.as_dyn_stride_mut(),
rhs.rb().column_vector().as_dyn_rows().as_dyn_stride(),
);
}
}
});
impl_op_assign!({
impl<
T: ComplexField,
Rows: Shape,
Cols: Shape,
LRStride: Stride,
LCStride: Stride,
RT: (Conjugate<Canonical = T>),
RRStride: Stride,
RCStride: Stride,
L: (for<'a> ReborrowMut<
'a,
Target = mat::Mut<'a, T, Rows, Cols, LRStride, LCStride>,
>),
R: (for<'a> Reborrow<
'a,
Target = mat::Ref<'a, RT, Rows, Cols, RRStride, RCStride>,
>),
> AddAssign<mat::generic::Mat<R>> for mat::generic::Mat<L>
{
fn add_assign(&mut self, rhs: _) {
fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
lhs: MatMut<'_, T>,
rhs: MatRef<'_, RT>,
) {
zip!(lhs, rhs).for_each(add_assign_fn::<T, RT>())
}
let lhs = self.rb_mut();
imp(
lhs.as_dyn_mut().as_dyn_stride_mut(),
rhs.rb().as_dyn().as_dyn_stride(),
);
}
}
impl<
T: ComplexField,
Rows: Shape,
LRStride: Stride,
RT: (Conjugate<Canonical = T>),
RRStride: Stride,
L: (for<'a> ReborrowMut<'a, Target = col::Mut<'a, T, Rows, LRStride>>),
R: (for<'a> Reborrow<'a, Target = col::Ref<'a, RT, Rows, RRStride>>),
> AddAssign<col::generic::Col<R>> for col::generic::Col<L>
{
fn add_assign(&mut self, rhs: _) {
fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
lhs: ColMut<'_, T>,
rhs: ColRef<'_, RT>,
) {
zip!(lhs, rhs).for_each(add_assign_fn::<T, RT>())
}
let lhs = self.rb_mut();
imp(
lhs.as_dyn_rows_mut().as_dyn_stride_mut(),
rhs.rb().as_dyn_rows().as_dyn_stride(),
);
}
}
impl<
T: ComplexField,
Cols: Shape,
LCStride: Stride,
RT: (Conjugate<Canonical = T>),
RCStride: Stride,
L: (for<'a> ReborrowMut<'a, Target = row::Mut<'a, T, Cols, LCStride>>),
R: (for<'a> Reborrow<'a, Target = row::Ref<'a, RT, Cols, RCStride>>),
> AddAssign<row::generic::Row<R>> for row::generic::Row<L>
{
fn add_assign(&mut self, rhs: _) {
fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
lhs: RowMut<'_, T>,
rhs: RowRef<'_, RT>,
) {
AddAssign::add_assign(
&mut lhs.transpose_mut(),
&rhs.transpose(),
)
}
let lhs = self.rb_mut();
imp(
lhs.as_dyn_cols_mut().as_dyn_stride_mut(),
rhs.rb().as_dyn_cols().as_dyn_stride(),
);
}
}
impl<
T: ComplexField,
Dim: Shape,
LStride: Stride,
RT: (Conjugate<Canonical = T>),
RStride: Stride,
L: (for<'a> ReborrowMut<'a, Target = diag::Mut<'a, T, Dim, LStride>>),
R: (for<'a> Reborrow<'a, Target = diag::Ref<'a, RT, Dim, RStride>>),
> AddAssign<diag::generic::Diag<R>> for diag::generic::Diag<L>
{
fn add_assign(&mut self, rhs: _) {
fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
lhs: ColMut<'_, T>,
rhs: ColRef<'_, RT>,
) {
AddAssign::add_assign(&mut { lhs }, &rhs)
}
let lhs = self.rb_mut();
imp(
lhs.column_vector_mut()
.as_dyn_rows_mut()
.as_dyn_stride_mut(),
rhs.rb().column_vector().as_dyn_rows().as_dyn_stride(),
);
}
}
});
impl_binop!({
impl<
T: ComplexField,
Rows: Shape,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
LRStride: Stride,
LCStride: Stride,
RT: (Conjugate<Canonical = T>),
RRStride: Stride,
RCStride: Stride,
L: (for<'a> Reborrow<
'a,
Target = mat::Ref<'a, LT, Rows, Cols, LRStride, LCStride>,
>),
R: (for<'a> Reborrow<
'a,
Target = mat::Ref<'a, RT, Rows, Cols, RRStride, RCStride>,
>),
> Add<mat::generic::Mat<R>> for mat::generic::Mat<L>
{
type Output = Mat<T, Rows, Cols>;
fn add(self, rhs: _) {
#[track_caller]
fn imp<
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: MatRef<'_, LT>,
rhs: MatRef<'_, RT>,
) -> Mat<T> {
assert!(all(
lhs.nrows() == rhs.nrows(),
lhs.ncols() == rhs.ncols()
));
zip!(lhs, rhs).map(add_fn::<LT, RT>())
}
let lhs = self.rb();
imp(
lhs.as_dyn().as_dyn_stride(),
rhs.rb().as_dyn().as_dyn_stride(),
)
.into_shape(lhs.nrows(), lhs.ncols())
}
}
impl<
T: ComplexField,
Rows: Shape,
LT: (Conjugate<Canonical = T>),
LRStride: Stride,
RT: (Conjugate<Canonical = T>),
RRStride: Stride,
L: (for<'a> Reborrow<'a, Target = col::Ref<'a, LT, Rows, LRStride>>),
R: (for<'a> Reborrow<'a, Target = col::Ref<'a, RT, Rows, RRStride>>),
> Add<col::generic::Col<R>> for col::generic::Col<L>
{
type Output = Col<T, Rows>;
fn add(self, rhs: _) {
#[track_caller]
fn imp<
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: ColRef<'_, LT>,
rhs: ColRef<'_, RT>,
) -> Col<T> {
assert!(all(
lhs.nrows() == rhs.nrows(),
lhs.ncols() == rhs.ncols()
));
zip!(lhs, rhs).map(add_fn::<LT, RT>())
}
let lhs = self.rb();
imp(
lhs.as_dyn_rows().as_dyn_stride(),
rhs.rb().as_dyn_rows().as_dyn_stride(),
)
.into_row_shape(lhs.nrows())
}
}
impl<
T: ComplexField,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
LCStride: Stride,
RT: (Conjugate<Canonical = T>),
RCStride: Stride,
L: (for<'a> Reborrow<'a, Target = row::Ref<'a, LT, Cols, LCStride>>),
R: (for<'a> Reborrow<'a, Target = row::Ref<'a, RT, Cols, RCStride>>),
> Add<row::generic::Row<R>> for row::generic::Row<L>
{
type Output = Row<T, Cols>;
fn add(self, rhs: _) {
#[track_caller]
fn imp<
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: RowRef<'_, LT>,
rhs: RowRef<'_, RT>,
) -> Row<T> {
assert!(all(
lhs.nrows() == rhs.nrows(),
lhs.ncols() == rhs.ncols()
));
(lhs.transpose() + rhs.transpose()).into_transpose()
}
let lhs = self.rb();
imp(
lhs.as_dyn_cols().as_dyn_stride(),
rhs.rb().as_dyn_cols().as_dyn_stride(),
)
.into_col_shape(lhs.ncols())
}
}
impl<
T: ComplexField,
Dim: Shape,
LT: (Conjugate<Canonical = T>),
LStride: Stride,
RT: (Conjugate<Canonical = T>),
RStride: Stride,
L: (for<'a> Reborrow<'a, Target = diag::Ref<'a, LT, Dim, LStride>>),
R: (for<'a> Reborrow<'a, Target = diag::Ref<'a, RT, Dim, RStride>>),
> Add<diag::generic::Diag<R>> for diag::generic::Diag<L>
{
type Output = Diag<T, Dim>;
fn add(self, rhs: _) {
#[track_caller]
fn imp<
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: ColRef<'_, LT>,
rhs: ColRef<'_, RT>,
) -> Col<T> {
assert!(all(lhs.nrows() == rhs.nrows()));
lhs + rhs
}
let lhs = self.rb();
imp(
lhs.column_vector().as_dyn_rows().as_dyn_stride(),
rhs.rb().column_vector().as_dyn_rows().as_dyn_stride(),
)
.into_row_shape(lhs.dim())
.into_diagonal()
}
}
});
impl_binop!({
impl<
T: ComplexField,
Rows: Shape,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
LRStride: Stride,
LCStride: Stride,
RT: (Conjugate<Canonical = T>),
RRStride: Stride,
RCStride: Stride,
L: (for<'a> Reborrow<
'a,
Target = mat::Ref<'a, LT, Rows, Cols, LRStride, LCStride>,
>),
R: (for<'a> Reborrow<
'a,
Target = mat::Ref<'a, RT, Rows, Cols, RRStride, RCStride>,
>),
> Sub<mat::generic::Mat<R>> for mat::generic::Mat<L>
{
type Output = Mat<T, Rows, Cols>;
fn sub(self, rhs: _) {
#[track_caller]
fn imp<
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: MatRef<'_, LT>,
rhs: MatRef<'_, RT>,
) -> Mat<T> {
assert!(all(
lhs.nrows() == rhs.nrows(),
lhs.ncols() == rhs.ncols()
));
zip!(lhs, rhs).map(sub_fn::<LT, RT>())
}
let lhs = self.rb();
imp(
lhs.as_dyn().as_dyn_stride(),
rhs.rb().as_dyn().as_dyn_stride(),
)
.into_shape(lhs.nrows(), lhs.ncols())
}
}
impl<
T: ComplexField,
Rows: Shape,
LT: (Conjugate<Canonical = T>),
LRStride: Stride,
RT: (Conjugate<Canonical = T>),
RRStride: Stride,
L: (for<'a> Reborrow<'a, Target = col::Ref<'a, LT, Rows, LRStride>>),
R: (for<'a> Reborrow<'a, Target = col::Ref<'a, RT, Rows, RRStride>>),
> Sub<col::generic::Col<R>> for col::generic::Col<L>
{
type Output = Col<T, Rows>;
fn sub(self, rhs: _) {
#[track_caller]
fn imp<
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: ColRef<'_, LT>,
rhs: ColRef<'_, RT>,
) -> Col<T> {
assert!(all(
lhs.nrows() == rhs.nrows(),
lhs.ncols() == rhs.ncols()
));
zip!(lhs, rhs).map(sub_fn::<LT, RT>())
}
let lhs = self.rb();
imp(
lhs.as_dyn_rows().as_dyn_stride(),
rhs.rb().as_dyn_rows().as_dyn_stride(),
)
.into_row_shape(lhs.nrows())
}
}
impl<
T: ComplexField,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
LCStride: Stride,
RT: (Conjugate<Canonical = T>),
RCStride: Stride,
L: (for<'a> Reborrow<'a, Target = row::Ref<'a, LT, Cols, LCStride>>),
R: (for<'a> Reborrow<'a, Target = row::Ref<'a, RT, Cols, RCStride>>),
> Sub<row::generic::Row<R>> for row::generic::Row<L>
{
type Output = Row<T, Cols>;
fn sub(self, rhs: _) {
#[track_caller]
fn imp<
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: RowRef<'_, LT>,
rhs: RowRef<'_, RT>,
) -> Row<T> {
assert!(all(
lhs.nrows() == rhs.nrows(),
lhs.ncols() == rhs.ncols()
));
(lhs.transpose() - rhs.transpose()).into_transpose()
}
let lhs = self.rb();
imp(
lhs.as_dyn_cols().as_dyn_stride(),
rhs.rb().as_dyn_cols().as_dyn_stride(),
)
.into_col_shape(lhs.ncols())
}
}
impl<
T: ComplexField,
Dim: Shape,
LT: (Conjugate<Canonical = T>),
LStride: Stride,
RT: (Conjugate<Canonical = T>),
RStride: Stride,
L: (for<'a> Reborrow<'a, Target = diag::Ref<'a, LT, Dim, LStride>>),
R: (for<'a> Reborrow<'a, Target = diag::Ref<'a, RT, Dim, RStride>>),
> Sub<diag::generic::Diag<R>> for diag::generic::Diag<L>
{
type Output = Diag<T, Dim>;
fn sub(self, rhs: _) {
#[track_caller]
fn imp<
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: ColRef<'_, LT>,
rhs: ColRef<'_, RT>,
) -> Col<T> {
assert!(all(lhs.nrows() == rhs.nrows()));
lhs - rhs
}
let lhs = self.rb();
imp(
lhs.column_vector().as_dyn_rows().as_dyn_stride(),
rhs.rb().column_vector().as_dyn_rows().as_dyn_stride(),
)
.into_row_shape(lhs.dim())
.into_diagonal()
}
}
});
impl_op!({
impl<
T: Conjugate,
Rows: Shape,
Cols: Shape,
RStride: Stride,
CStride: Stride,
Inner: (for<'a> Reborrow<
'a,
Target = mat::Ref<'a, T, Rows, Cols, RStride, CStride>,
>),
> Neg for mat::generic::Mat<Inner>
{
type Output = Mat<T::Canonical, Rows, Cols>;
fn neg(self) {
#[track_caller]
fn imp<T: Conjugate>(A: MatRef<'_, T>) -> Mat<T::Canonical> {
zip!(A).map(neg_fn::<T>())
}
let A = self.rb();
imp(A.as_dyn().as_dyn_stride()).into_shape(A.nrows(), A.ncols())
}
}
impl<
T: Conjugate,
Rows: Shape,
RStride: Stride,
Inner: (for<'a> Reborrow<'a, Target = col::Ref<'a, T, Rows, RStride>>),
> Neg for col::generic::Col<Inner>
{
type Output = Col<T::Canonical, Rows>;
fn neg(self) {
#[track_caller]
fn imp<T: Conjugate>(A: ColRef<'_, T>) -> Col<T::Canonical> {
zip!(A).map(neg_fn::<T>())
}
let A = self.rb();
imp(A.as_dyn_rows().as_dyn_stride()).into_row_shape(A.nrows())
}
}
impl<
T: Conjugate,
Cols: Shape,
CStride: Stride,
Inner: (for<'a> Reborrow<'a, Target = row::Ref<'a, T, Cols, CStride>>),
> Neg for row::generic::Row<Inner>
{
type Output = Row<T::Canonical, Cols>;
fn neg(self) {
#[track_caller]
fn imp<T: Conjugate>(A: RowRef<'_, T>) -> Row<T::Canonical> {
(-A.transpose()).into_transpose()
}
let A = self.rb();
imp(A.as_dyn_cols().as_dyn_stride()).into_col_shape(A.ncols())
}
}
impl<
T: Conjugate,
Dim: Shape,
Stride: (crate::Stride),
Inner: (for<'a> Reborrow<'a, Target = diag::Ref<'a, T, Dim, Stride>>),
> Neg for diag::generic::Diag<Inner>
{
type Output = Diag<T::Canonical, Dim>;
fn neg(self) {
#[track_caller]
fn imp<T: Conjugate>(A: ColRef<'_, T>) -> Col<T::Canonical> {
-A
}
let A = self.rb().column_vector();
imp(A.as_dyn_rows().as_dyn_stride())
.into_row_shape(A.nrows())
.into_diagonal()
}
}
});
#[inline]
fn add_fn<
LhsT: Conjugate<Canonical: ComplexField>,
RhsT: Conjugate<Canonical = LhsT::Canonical>,
>()
-> impl FnMut(linalg::zip::Zip<&LhsT, linalg::zip::Last<&RhsT>>) -> LhsT::Canonical
{
#[inline(always)]
move |unzip!(a, b)| Conj::apply(a) + Conj::apply(b)
}
#[inline]
fn sub_fn<
LhsT: Conjugate<Canonical: ComplexField>,
RhsT: Conjugate<Canonical = LhsT::Canonical>,
>()
-> impl FnMut(linalg::zip::Zip<&LhsT, linalg::zip::Last<&RhsT>>) -> LhsT::Canonical
{
#[inline(always)]
move |unzip!(a, b)| Conj::apply(a) - Conj::apply(b)
}
#[inline]
fn mul_fn<
LhsT: Conjugate<Canonical: ComplexField>,
RhsT: Conjugate<Canonical = LhsT::Canonical>,
>()
-> impl FnMut(linalg::zip::Zip<&LhsT, linalg::zip::Last<&RhsT>>) -> LhsT::Canonical
{
#[inline(always)]
move |unzip!(a, b)| Conj::apply(a) * Conj::apply(b)
}
#[inline]
fn neg_fn<LhsT: Conjugate<Canonical: ComplexField>>()
-> impl FnMut(linalg::zip::Last<&LhsT>) -> LhsT::Canonical {
#[inline(always)]
move |unzip!(a)| -Conj::apply(a)
}
#[inline]
fn add_assign_fn<LhsT: ComplexField, RhsT: Conjugate<Canonical = LhsT>>()
-> impl FnMut(linalg::zip::Zip<&mut LhsT, linalg::zip::Last<&RhsT>>) {
#[inline(always)]
move |unzip!(a, b)| *a = Conj::apply(a) + Conj::apply(b)
}
#[inline]
fn sub_assign_fn<LhsT: ComplexField, RhsT: Conjugate<Canonical = LhsT>>()
-> impl FnMut(linalg::zip::Zip<&mut LhsT, linalg::zip::Last<&RhsT>>) {
#[inline(always)]
move |unzip!(a, b)| *a = Conj::apply(a) - Conj::apply(b)
}
mod matmul {
use super::*;
use crate::assert;
impl_binop!({
impl<
T: ComplexField,
Rows: Shape,
Cols: Shape,
Depth: Shape,
LT: (Conjugate<Canonical = T>),
LRStride: Stride,
LCStride: Stride,
RT: (Conjugate<Canonical = T>),
RRStride: Stride,
RCStride: Stride,
L: (for<'a> Reborrow<
'a,
Target = mat::Ref<'a, LT, Rows, Depth, LRStride, LCStride>,
>),
R: (for<'a> Reborrow<
'a,
Target = mat::Ref<'a, RT, Depth, Cols, RRStride, RCStride>,
>),
> Mul<mat::generic::Mat<R>> for mat::generic::Mat<L>
{
type Output = Mat<T, Rows, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: MatRef<'_, LT>,
rhs: MatRef<'_, RT>,
) -> Mat<T> {
assert!(lhs.ncols() == rhs.nrows());
let mut out = Mat::zeros(lhs.nrows(), rhs.ncols());
crate::linalg::matmul::matmul(
out.as_mut(),
Accum::Replace,
lhs,
rhs,
T::one_impl(),
get_global_parallelism(),
);
out
}
let lhs = self.rb();
let rhs = rhs.rb();
imp(lhs.as_dyn().as_dyn_stride(), rhs.as_dyn().as_dyn_stride())
.into_shape(lhs.nrows(), rhs.ncols())
}
}
impl<
T: ComplexField,
Rows: Shape,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
LRStride: Stride,
LCStride: Stride,
RT: (Conjugate<Canonical = T>),
RRStride: Stride,
L: (for<'a> Reborrow<
'a,
Target = mat::Ref<'a, LT, Rows, Cols, LRStride, LCStride>,
>),
R: (for<'a> Reborrow<'a, Target = col::Ref<'a, RT, Cols, RRStride>>),
> Mul<col::generic::Col<R>> for mat::generic::Mat<L>
{
type Output = Col<T, Rows>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: MatRef<'_, LT>,
rhs: ColRef<'_, RT>,
) -> Col<T> {
assert!(lhs.ncols() == rhs.nrows());
let mut out = Col::zeros(lhs.nrows());
crate::linalg::matmul::matmul(
out.as_mut(),
Accum::Replace,
lhs,
rhs,
T::one_impl(),
get_global_parallelism(),
);
out
}
let lhs = self.rb();
let rhs = rhs.rb();
imp(
lhs.as_dyn().as_dyn_stride(),
rhs.as_dyn_rows().as_dyn_stride(),
)
.into_row_shape(lhs.nrows())
}
}
impl<
T: ComplexField,
Rows: Shape,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
LCStride: Stride,
RT: (Conjugate<Canonical = T>),
RRStride: Stride,
RCStride: Stride,
L: (for<'a> Reborrow<'a, Target = row::Ref<'a, LT, Rows, LCStride>>),
R: (for<'a> Reborrow<
'a,
Target = mat::Ref<'a, RT, Rows, Cols, RRStride, RCStride>,
>),
> Mul<mat::generic::Mat<R>> for row::generic::Row<L>
{
type Output = Row<T, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: RowRef<'_, LT>,
rhs: MatRef<'_, RT>,
) -> Row<T> {
assert!(lhs.ncols() == rhs.nrows());
let mut out = Row::zeros(rhs.ncols());
crate::linalg::matmul::matmul(
out.as_mut(),
Accum::Replace,
lhs,
rhs,
T::one_impl(),
get_global_parallelism(),
);
out
}
let lhs = self.rb();
let rhs = rhs.rb();
imp(
lhs.as_dyn_cols().as_dyn_stride(),
rhs.as_dyn().as_dyn_stride(),
)
.into_col_shape(rhs.ncols())
}
}
impl<
T: ComplexField,
Dim: Shape,
LT: (Conjugate<Canonical = T>),
LCStride: Stride,
RT: (Conjugate<Canonical = T>),
RRStride: Stride,
L: (for<'a> Reborrow<'a, Target = row::Ref<'a, LT, Dim, LCStride>>),
R: (for<'a> Reborrow<'a, Target = col::Ref<'a, RT, Dim, RRStride>>),
> Mul<col::generic::Col<R>> for row::generic::Row<L>
{
type Output = T;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: RowRef<'_, LT>,
rhs: ColRef<'_, RT>,
) -> T {
assert!(lhs.ncols() == rhs.nrows());
let mut out = [[zero::<T>()]];
crate::linalg::matmul::matmul(
MatMut::from_row_major_array_mut(&mut out),
Accum::Replace,
lhs.as_mat(),
rhs.as_mat(),
T::one_impl(),
get_global_parallelism(),
);
let [[out]] = out;
out
}
let lhs = self.rb();
let rhs = rhs.rb();
imp(
lhs.as_dyn_cols().as_dyn_stride(),
rhs.as_dyn_rows().as_dyn_stride(),
)
}
}
impl<
T: ComplexField,
Rows: Shape,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
LRStride: Stride,
RT: (Conjugate<Canonical = T>),
RCStride: Stride,
L: (for<'a> Reborrow<'a, Target = col::Ref<'a, LT, Rows, LRStride>>),
R: (for<'a> Reborrow<'a, Target = row::Ref<'a, RT, Cols, RCStride>>),
> Mul<row::generic::Row<R>> for col::generic::Col<L>
{
type Output = Mat<T, Rows, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: ColRef<'_, LT>,
rhs: RowRef<'_, RT>,
) -> Mat<T> {
assert!(lhs.ncols() == rhs.nrows());
let mut out = Mat::zeros(lhs.nrows(), rhs.ncols());
crate::linalg::matmul::matmul(
out.rb_mut(),
Accum::Replace,
lhs,
rhs,
T::one_impl(),
get_global_parallelism(),
);
out
}
let lhs = self.rb();
let rhs = rhs.rb();
imp(
lhs.as_dyn_rows().as_dyn_stride(),
rhs.as_dyn_cols().as_dyn_stride(),
)
.into_shape(lhs.nrows(), rhs.ncols())
}
}
impl<
T: ComplexField,
Dim: Shape,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
LStride: Stride,
RT: (Conjugate<Canonical = T>),
RRStride: Stride,
RCStride: Stride,
L: (for<'a> Reborrow<'a, Target = diag::Ref<'a, LT, Dim, LStride>>),
R: (for<'a> Reborrow<
'a,
Target = mat::Ref<'a, RT, Dim, Cols, RRStride, RCStride>,
>),
> Mul<mat::generic::Mat<R>> for diag::generic::Diag<L>
{
type Output = Mat<T, Dim, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: ColRef<'_, LT>,
rhs: MatRef<'_, RT>,
) -> Mat<T> {
let lhs_dim = lhs.nrows();
let rhs_nrows = rhs.nrows();
assert!(lhs_dim == rhs_nrows);
Mat::from_fn(rhs.nrows(), rhs.ncols(), |i, j| {
Conj::apply(lhs.at(i)) * Conj::apply(rhs.at(i, j))
})
}
let lhs = self.rb();
let rhs = rhs.rb();
imp(
lhs.column_vector().as_dyn_rows().as_dyn_stride(),
rhs.as_dyn().as_dyn_stride(),
)
.into_shape(rhs.nrows(), rhs.ncols())
}
}
impl<
T: ComplexField,
Dim: Shape,
LT: (Conjugate<Canonical = T>),
LStride: Stride,
RT: (Conjugate<Canonical = T>),
RRStride: Stride,
L: (for<'a> Reborrow<'a, Target = diag::Ref<'a, LT, Dim, LStride>>),
R: (for<'a> Reborrow<'a, Target = col::Ref<'a, RT, Dim, RRStride>>),
> Mul<col::generic::Col<R>> for diag::generic::Diag<L>
{
type Output = Col<T, Dim>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: ColRef<'_, LT>,
rhs: ColRef<'_, RT>,
) -> Col<T> {
let lhs_dim = lhs.nrows();
let rhs_nrows = rhs.nrows();
assert!(lhs_dim == rhs_nrows);
zip!(lhs, rhs).map(mul_fn::<LT, RT>())
}
let lhs = self.rb();
let rhs = rhs.rb();
imp(
lhs.column_vector().as_dyn_rows().as_dyn_stride(),
rhs.as_dyn_rows().as_dyn_stride(),
)
.into_row_shape(rhs.nrows())
}
}
impl<
T: ComplexField,
Dim: Shape,
Rows: Shape,
LT: (Conjugate<Canonical = T>),
LRStride: Stride,
LCStride: Stride,
RT: (Conjugate<Canonical = T>),
RStride: Stride,
L: (for<'a> Reborrow<
'a,
Target = mat::Ref<'a, LT, Rows, Dim, LRStride, LCStride>,
>),
R: (for<'a> Reborrow<'a, Target = diag::Ref<'a, RT, Dim, RStride>>),
> Mul<diag::generic::Diag<R>> for mat::generic::Mat<L>
{
type Output = Mat<T, Rows, Dim>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: MatRef<'_, LT>,
rhs: ColRef<'_, RT>,
) -> Mat<T> {
let lhs_ncols = lhs.ncols();
let rhs_dim = rhs.nrows();
assert!(lhs_ncols == rhs_dim);
let mut f = mul_fn::<LT, RT>();
Mat::from_fn(lhs.nrows(), lhs.ncols(), |i, j| {
f(linalg::zip::Zip(
lhs.at(i, j),
linalg::zip::Last(rhs.at(j)),
))
})
}
let lhs = self.rb();
let rhs = rhs.rb();
imp(
lhs.as_dyn().as_dyn_stride(),
rhs.column_vector().as_dyn_rows().as_dyn_stride(),
)
.into_shape(lhs.nrows(), lhs.ncols())
}
}
impl<
T: ComplexField,
Dim: Shape,
LT: (Conjugate<Canonical = T>),
LCStride: Stride,
RT: (Conjugate<Canonical = T>),
RStride: Stride,
L: (for<'a> Reborrow<'a, Target = row::Ref<'a, LT, Dim, LCStride>>),
R: (for<'a> Reborrow<'a, Target = diag::Ref<'a, RT, Dim, RStride>>),
> Mul<diag::generic::Diag<R>> for row::generic::Row<L>
{
type Output = Row<T, Dim>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: RowRef<'_, LT>,
rhs: ColRef<'_, RT>,
) -> Row<T> {
let lhs_ncols = lhs.ncols();
let rhs_dim = rhs.nrows();
assert!(lhs_ncols == rhs_dim);
(rhs.as_diagonal() * lhs.transpose()).into_transpose()
}
let lhs = self.rb();
let rhs = rhs.rb();
imp(
lhs.as_dyn_cols().as_dyn_stride(),
rhs.column_vector().as_dyn_rows().as_dyn_stride(),
)
.into_col_shape(lhs.ncols())
}
}
impl<
T: ComplexField,
Dim: Shape,
LT: (Conjugate<Canonical = T>),
LStride: Stride,
RT: (Conjugate<Canonical = T>),
RStride: Stride,
L: (for<'a> Reborrow<'a, Target = diag::Ref<'a, LT, Dim, LStride>>),
R: (for<'a> Reborrow<'a, Target = diag::Ref<'a, RT, Dim, RStride>>),
> Mul<diag::generic::Diag<R>> for diag::generic::Diag<L>
{
type Output = Diag<T, Dim>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: ColRef<'_, LT>,
rhs: ColRef<'_, RT>,
) -> Col<T> {
let lhs_dim = lhs.nrows();
let rhs_dim = rhs.nrows();
assert!(lhs_dim == rhs_dim);
lhs.as_diagonal() * rhs
}
let lhs = self.rb().column_vector();
let rhs = rhs.rb().column_vector();
imp(
lhs.as_dyn_rows().as_dyn_stride(),
rhs.as_dyn_rows().as_dyn_stride(),
)
.into_row_shape(lhs.nrows())
.into_diagonal()
}
}
});
}
impl_binop!({
impl<
I: Index,
N: Shape,
L: (for<'a> Reborrow<'a, Target = perm::Ref<'a, I, N>>),
R: (for<'a> Reborrow<'a, Target = perm::Ref<'a, I, N>>),
> Mul<perm::generic::Perm<R>> for perm::generic::Perm<L>
{
type Output = Perm<I, N>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<I: Index>(
lhs: PermRef<'_, I>,
rhs: PermRef<'_, I>,
) -> Perm<I> {
assert!(lhs.len() == rhs.len());
let truncate = <I::Signed as SignedIndex>::truncate;
let mut fwd =
alloc::vec![I::from_signed(truncate(0)); lhs.len()]
.into_boxed_slice();
let mut inv =
alloc::vec![I::from_signed(truncate(0)); lhs.len()]
.into_boxed_slice();
for (fwd, rhs) in fwd.iter_mut().zip(rhs.arrays().0) {
*fwd = lhs.arrays().0[rhs.to_signed().zx()];
}
for (i, fwd) in fwd.iter().enumerate() {
inv[fwd.to_signed().zx()] =
I::from_signed(I::Signed::truncate(i));
}
Perm::new_checked(fwd, inv, lhs.len())
}
let lhs = self.rb();
let rhs = rhs.rb();
let N = lhs.len();
let n = N.unbound();
imp(lhs.as_shape(n), rhs.as_shape(n)).into_shape(N)
}
}
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
RT: (Conjugate<Canonical = T>),
RRStride: Stride,
RCStride: Stride,
L: (for<'a> Reborrow<'a, Target = perm::Ref<'a, I, Rows>>),
R: (for<'a> Reborrow<
'a,
Target = mat::Ref<'a, RT, Rows, Cols, RRStride, RCStride>,
>),
> Mul<mat::generic::Mat<R>> for perm::generic::Perm<L>
{
type Output = Mat<T, Rows, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<I: Index, T: ComplexField, RT: Conjugate<Canonical = T>>(
lhs: PermRef<'_, I>,
rhs: MatRef<'_, RT>,
) -> Mat<T> {
with_dim!(M, rhs.nrows());
with_dim!(N, rhs.ncols());
let rhs = rhs.as_shape(M, N);
let lhs = lhs.as_shape(M);
let mut out = Mat::zeros(rhs.nrows(), rhs.ncols());
let fwd = lhs.bound_arrays().0;
for j in rhs.ncols().indices() {
for i in rhs.nrows().indices() {
let fwd = fwd[i];
let rhs = rhs.at(fwd.zx(), j);
out[(i, j)] = Conj::apply(rhs);
}
}
out.into_shape(*M, *N)
}
let lhs = self.rb();
let rhs = rhs.rb();
let m = rhs.nrows().unbound();
imp(lhs.as_shape(m), rhs.as_dyn().as_dyn_stride())
.into_shape(rhs.nrows(), rhs.ncols())
}
}
impl<
I: Index,
T: ComplexField,
Rows: Shape,
RT: (Conjugate<Canonical = T>),
RRStride: Stride,
L: (for<'a> Reborrow<'a, Target = perm::Ref<'a, I, Rows>>),
R: (for<'a> Reborrow<'a, Target = col::Ref<'a, RT, Rows, RRStride>>),
> Mul<col::generic::Col<R>> for perm::generic::Perm<L>
{
type Output = Col<T, Rows>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<I: Index, T: ComplexField, RT: Conjugate<Canonical = T>>(
lhs: PermRef<'_, I>,
rhs: ColRef<'_, RT>,
) -> Col<T> {
with_dim!(M, rhs.nrows());
let rhs = rhs.as_row_shape(M);
let lhs = lhs.as_shape(M);
let mut out = Col::zeros(rhs.nrows());
let fwd = lhs.bound_arrays().0;
for i in rhs.nrows().indices() {
let fwd = fwd[i];
let rhs = rhs.at(fwd.zx());
out[i] = Conj::apply(rhs);
}
out.into_row_shape(*M)
}
let lhs = self.rb();
let rhs = rhs.rb();
let m = rhs.nrows().unbound();
imp(lhs.as_shape(m), rhs.as_dyn_rows().as_dyn_stride())
.into_row_shape(rhs.nrows())
}
}
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
LRStride: Stride,
LCStride: Stride,
L: (for<'a> Reborrow<
'a,
Target = mat::Ref<'a, LT, Rows, Cols, LRStride, LCStride>,
>),
R: (for<'a> Reborrow<'a, Target = perm::Ref<'a, I, Cols>>),
> Mul<perm::generic::Perm<R>> for mat::generic::Mat<L>
{
type Output = Mat<T, Rows, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<I: Index, T: ComplexField, LT: Conjugate<Canonical = T>>(
lhs: MatRef<'_, LT>,
rhs: PermRef<'_, I>,
) -> Mat<T> {
with_dim!(M, lhs.nrows());
with_dim!(N, lhs.ncols());
let lhs = lhs.as_shape(M, N);
let rhs = rhs.as_shape(N);
let mut out = Mat::zeros(M, N);
let inv = rhs.bound_arrays().1;
for j in N.indices() {
let inv = inv[j];
for i in M.indices() {
let lhs = lhs.at(i, inv.zx());
out[(i, j)] = Conj::apply(lhs);
}
}
out.into_shape(*M, *N)
}
let lhs = self.rb();
let rhs = rhs.rb();
let n = lhs.ncols().unbound();
imp(lhs.as_dyn().as_dyn_stride(), rhs.as_shape(n))
.into_shape(lhs.nrows(), lhs.ncols())
}
}
impl<
I: Index,
T: ComplexField,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
LCStride: Stride,
L: (for<'a> Reborrow<'a, Target = row::Ref<'a, LT, Cols, LCStride>>),
R: (for<'a> Reborrow<'a, Target = perm::Ref<'a, I, Cols>>),
> Mul<perm::generic::Perm<R>> for row::generic::Row<L>
{
type Output = Row<T, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<I: Index, T: ComplexField, LT: Conjugate<Canonical = T>>(
lhs: RowRef<'_, LT>,
rhs: PermRef<'_, I>,
) -> Row<T> {
with_dim!(N, lhs.ncols());
let lhs = lhs.as_col_shape(N);
let rhs = rhs.as_shape(N);
let mut out = Row::zeros(N);
let inv = rhs.bound_arrays().1;
for j in N.indices() {
let inv = inv[j];
let lhs = lhs.at(inv.zx());
out[j] = Conj::apply(lhs);
}
out.into_col_shape(*N)
}
let lhs = self.rb();
let rhs = rhs.rb();
let n = lhs.ncols().unbound();
imp(lhs.as_dyn_cols().as_dyn_stride(), rhs.as_shape(n))
.into_col_shape(lhs.ncols())
}
}
});
impl_binop!({
impl<
T: ComplexField,
Rows: Shape,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
LRStride: Stride,
LCStride: Stride,
L: (for<'a> Reborrow<
'a,
Target = mat::Ref<'a, LT, Rows, Cols, LRStride, LCStride>,
>),
> Mul<Scale<T>> for mat::generic::Mat<L>
{
type Output = Mat<T, Rows, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
lhs: MatRef<'_, LT>,
rhs: &T,
) -> Mat<T> {
zip!(lhs).map(|unzip!(x)| Conj::apply(x) * rhs)
}
let lhs = self.rb();
let rhs = &rhs.0;
imp(lhs.as_dyn().as_dyn_stride(), rhs)
.into_shape(lhs.nrows(), lhs.ncols())
}
}
impl<
T: ComplexField,
Rows: Shape,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
LRStride: Stride,
LCStride: Stride,
L: (for<'a> Reborrow<
'a,
Target = mat::Ref<'a, LT, Rows, Cols, LRStride, LCStride>,
>),
> Div<Scale<T>> for mat::generic::Mat<L>
{
type Output = Mat<T, Rows, Cols>;
fn div(self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
lhs: MatRef<'_, LT>,
rhs: &T,
) -> Mat<T> {
lhs * Scale(rhs.recip())
}
let lhs = self.rb();
let rhs = &rhs.0;
imp(lhs.as_dyn().as_dyn_stride(), rhs)
.into_shape(lhs.nrows(), lhs.ncols())
}
}
impl<
T: ComplexField,
Rows: Shape,
Cols: Shape,
RT: (Conjugate<Canonical = T>),
RRStride: Stride,
RCStride: Stride,
R: (for<'a> Reborrow<
'a,
Target = mat::Ref<'a, RT, Rows, Cols, RRStride, RCStride>,
>),
> Mul<mat::generic::Mat<R>> for Scale<T>
{
type Output = Mat<T, Rows, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
lhs: &T,
rhs: MatRef<'_, RT>,
) -> Mat<T> {
zip!(rhs).map(|unzip!(x)| lhs * Conj::apply(x))
}
let lhs = &self.0;
let rhs = rhs.rb();
imp(lhs, rhs.as_dyn().as_dyn_stride())
.into_shape(rhs.nrows(), rhs.ncols())
}
}
});
impl_binop!({
impl<
T: ComplexField,
Rows: Shape,
LT: (Conjugate<Canonical = T>),
LRStride: Stride,
L: (for<'a> Reborrow<'a, Target = col::Ref<'a, LT, Rows, LRStride>>),
> Mul<Scale<T>> for col::generic::Col<L>
{
type Output = Col<T, Rows>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
lhs: ColRef<'_, LT>,
rhs: &T,
) -> Col<T> {
zip!(lhs).map(|unzip!(x)| Conj::apply(x) * rhs)
}
let lhs = self.rb();
let rhs = &rhs.0;
imp(lhs.as_dyn_rows().as_dyn_stride(), rhs)
.into_row_shape(lhs.nrows())
}
}
impl<
T: ComplexField,
Rows: Shape,
LT: (Conjugate<Canonical = T>),
LRStride: Stride,
L: (for<'a> Reborrow<'a, Target = col::Ref<'a, LT, Rows, LRStride>>),
> Div<Scale<T>> for col::generic::Col<L>
{
type Output = Col<T, Rows>;
fn div(self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
lhs: ColRef<'_, LT>,
rhs: &T,
) -> Col<T> {
lhs * Scale(rhs.recip())
}
let lhs = self.rb();
let rhs = &rhs.0;
imp(lhs.as_dyn_rows().as_dyn_stride(), rhs)
.into_row_shape(lhs.nrows())
}
}
impl<
T: ComplexField,
Rows: Shape,
RT: (Conjugate<Canonical = T>),
RRStride: Stride,
R: (for<'a> Reborrow<'a, Target = col::Ref<'a, RT, Rows, RRStride>>),
> Mul<col::generic::Col<R>> for Scale<T>
{
type Output = Col<T, Rows>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
lhs: &T,
rhs: ColRef<'_, RT>,
) -> Col<T> {
zip!(rhs).map(|unzip!(x)| lhs * Conj::apply(x))
}
let lhs = &self.0;
let rhs = rhs.rb();
imp(lhs, rhs.as_dyn_rows().as_dyn_stride())
.into_row_shape(rhs.nrows())
}
}
});
impl_binop!({
impl<
T: ComplexField,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
LCStride: Stride,
L: (for<'a> Reborrow<'a, Target = row::Ref<'a, LT, Cols, LCStride>>),
> Mul<Scale<T>> for row::generic::Row<L>
{
type Output = Row<T, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
lhs: RowRef<'_, LT>,
rhs: &T,
) -> Row<T> {
(lhs.transpose() * Scale::from_ref(rhs)).into_transpose()
}
let lhs = self.rb();
let rhs = &rhs.0;
imp(lhs.as_dyn_cols().as_dyn_stride(), rhs)
.into_col_shape(lhs.ncols())
}
}
impl<
T: ComplexField,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
LCStride: Stride,
L: (for<'a> Reborrow<'a, Target = row::Ref<'a, LT, Cols, LCStride>>),
> Div<Scale<T>> for row::generic::Row<L>
{
type Output = Row<T, Cols>;
fn div(self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
lhs: RowRef<'_, LT>,
rhs: &T,
) -> Row<T> {
lhs * Scale(rhs.recip())
}
let lhs = self.rb();
let rhs = &rhs.0;
imp(lhs.as_dyn_cols().as_dyn_stride(), rhs)
.into_col_shape(lhs.ncols())
}
}
impl<
T: ComplexField,
Cols: Shape,
RT: (Conjugate<Canonical = T>),
RCStride: Stride,
R: (for<'a> Reborrow<'a, Target = row::Ref<'a, RT, Cols, RCStride>>),
> Mul<row::generic::Row<R>> for Scale<T>
{
type Output = Row<T, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
lhs: &T,
rhs: RowRef<'_, RT>,
) -> Row<T> {
(Scale::from_ref(lhs) * rhs.transpose()).into_transpose()
}
let lhs = &self.0;
let rhs = rhs.rb();
imp(lhs, rhs.as_dyn_cols().as_dyn_stride())
.into_col_shape(rhs.ncols())
}
}
});
impl_binop!({
impl<
T: ComplexField,
Dim: Shape,
LT: (Conjugate<Canonical = T>),
LStride: Stride,
L: (for<'a> Reborrow<'a, Target = diag::Ref<'a, LT, Dim, LStride>>),
> Mul<Scale<T>> for diag::generic::Diag<L>
{
type Output = Diag<T, Dim>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
lhs: ColRef<'_, LT>,
rhs: &T,
) -> Col<T> {
lhs * Scale::from_ref(rhs)
}
let lhs = self.rb().column_vector();
let rhs = &rhs.0;
imp(lhs.as_dyn_rows().as_dyn_stride(), rhs)
.into_row_shape(lhs.nrows())
.into_diagonal()
}
}
impl<
T: ComplexField,
Dim: Shape,
LT: (Conjugate<Canonical = T>),
LStride: Stride,
L: (for<'a> Reborrow<'a, Target = diag::Ref<'a, LT, Dim, LStride>>),
> Div<Scale<T>> for diag::generic::Diag<L>
{
type Output = Diag<T, Dim>;
fn div(self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
lhs: ColRef<'_, LT>,
rhs: &T,
) -> Col<T> {
lhs * Scale(rhs.recip())
}
let lhs = self.rb().column_vector();
let rhs = &rhs.0;
imp(lhs.as_dyn_rows().as_dyn_stride(), rhs)
.into_row_shape(lhs.nrows())
.into_diagonal()
}
}
impl<
T: ComplexField,
Dim: Shape,
RT: (Conjugate<Canonical = T>),
RStride: Stride,
R: (for<'a> Reborrow<'a, Target = diag::Ref<'a, RT, Dim, RStride>>),
> Mul<diag::generic::Diag<R>> for Scale<T>
{
type Output = Diag<T, Dim>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
lhs: &T,
rhs: ColRef<'_, RT>,
) -> Col<T> {
Scale::from_ref(lhs) * rhs
}
let lhs = &self.0;
let rhs = rhs.rb().column_vector();
imp(lhs, rhs.as_dyn_rows().as_dyn_stride())
.into_row_shape(rhs.nrows())
.into_diagonal()
}
}
});
impl_binop!({
impl<
T: ComplexField,
Rows: Shape,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
LRStride: Stride,
LCStride: Stride,
L: (for<'a> Reborrow<
'a,
Target = mat::Ref<'a, LT, Rows, Cols, LRStride, LCStride>,
>),
> Mul<f64> for mat::generic::Mat<L>
{
type Output = Mat<T, Rows, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
lhs: MatRef<'_, LT>,
rhs: &T,
) -> Mat<T> {
lhs * Scale::from_ref(rhs)
}
let lhs = self.rb();
let rhs = &from_f64::<T>(*rhs);
imp(lhs.as_dyn().as_dyn_stride(), rhs)
.into_shape(lhs.nrows(), lhs.ncols())
}
}
impl<
T: ComplexField,
Rows: Shape,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
LRStride: Stride,
LCStride: Stride,
L: (for<'a> Reborrow<
'a,
Target = mat::Ref<'a, LT, Rows, Cols, LRStride, LCStride>,
>),
> Div<f64> for mat::generic::Mat<L>
{
type Output = Mat<T, Rows, Cols>;
fn div(self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
lhs: MatRef<'_, LT>,
rhs: &T,
) -> Mat<T> {
lhs * Scale(rhs.recip())
}
let lhs = self.rb();
let rhs = &from_f64::<T>(*rhs);
imp(lhs.as_dyn().as_dyn_stride(), rhs)
.into_shape(lhs.nrows(), lhs.ncols())
}
}
impl<
T: ComplexField,
Rows: Shape,
Cols: Shape,
RT: (Conjugate<Canonical = T>),
RRStride: Stride,
RCStride: Stride,
R: (for<'a> Reborrow<
'a,
Target = mat::Ref<'a, RT, Rows, Cols, RRStride, RCStride>,
>),
> Mul<mat::generic::Mat<R>> for f64
{
type Output = Mat<T, Rows, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
lhs: &T,
rhs: MatRef<'_, RT>,
) -> Mat<T> {
Scale::from_ref(lhs) * rhs
}
let lhs = &from_f64::<T>(*self);
let rhs = rhs.rb();
imp(lhs, rhs.as_dyn().as_dyn_stride())
.into_shape(rhs.nrows(), rhs.ncols())
}
}
});
impl_binop!({
impl<
T: ComplexField,
Rows: Shape,
LT: (Conjugate<Canonical = T>),
LRStride: Stride,
L: (for<'a> Reborrow<'a, Target = col::Ref<'a, LT, Rows, LRStride>>),
> Mul<f64> for col::generic::Col<L>
{
type Output = Col<T, Rows>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
lhs: ColRef<'_, LT>,
rhs: &T,
) -> Col<T> {
lhs * Scale::from_ref(rhs)
}
let lhs = self.rb();
let rhs = &from_f64::<T>(*rhs);
imp(lhs.as_dyn_rows().as_dyn_stride(), rhs)
.into_row_shape(lhs.nrows())
}
}
impl<
T: ComplexField,
Rows: Shape,
LT: (Conjugate<Canonical = T>),
LRStride: Stride,
L: (for<'a> Reborrow<'a, Target = col::Ref<'a, LT, Rows, LRStride>>),
> Div<f64> for col::generic::Col<L>
{
type Output = Col<T, Rows>;
fn div(self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
lhs: ColRef<'_, LT>,
rhs: &T,
) -> Col<T> {
lhs * Scale(rhs.recip())
}
let lhs = self.rb();
let rhs = &from_f64::<T>(*rhs);
imp(lhs.as_dyn_rows().as_dyn_stride(), rhs)
.into_row_shape(lhs.nrows())
}
}
impl<
T: ComplexField,
Rows: Shape,
RT: (Conjugate<Canonical = T>),
RRStride: Stride,
R: (for<'a> Reborrow<'a, Target = col::Ref<'a, RT, Rows, RRStride>>),
> Mul<col::generic::Col<R>> for f64
{
type Output = Col<T, Rows>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
lhs: &T,
rhs: ColRef<'_, RT>,
) -> Col<T> {
Scale::from_ref(lhs) * rhs
}
let lhs = &from_f64::<T>(*self);
let rhs = rhs.rb();
imp(lhs, rhs.as_dyn_rows().as_dyn_stride())
.into_row_shape(rhs.nrows())
}
}
});
impl_binop!({
impl<
T: ComplexField,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
LCStride: Stride,
L: (for<'a> Reborrow<'a, Target = row::Ref<'a, LT, Cols, LCStride>>),
> Mul<f64> for row::generic::Row<L>
{
type Output = Row<T, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
lhs: RowRef<'_, LT>,
rhs: &T,
) -> Row<T> {
(lhs.transpose() * Scale::from_ref(rhs)).into_transpose()
}
let lhs = self.rb();
let rhs = &from_f64::<T>(*rhs);
imp(lhs.as_dyn_cols().as_dyn_stride(), rhs)
.into_col_shape(lhs.ncols())
}
}
impl<
T: ComplexField,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
LCStride: Stride,
L: (for<'a> Reborrow<'a, Target = row::Ref<'a, LT, Cols, LCStride>>),
> Div<f64> for row::generic::Row<L>
{
type Output = Row<T, Cols>;
fn div(self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
lhs: RowRef<'_, LT>,
rhs: &T,
) -> Row<T> {
lhs * Scale(rhs.recip())
}
let lhs = self.rb();
let rhs = &from_f64::<T>(*rhs);
imp(lhs.as_dyn_cols().as_dyn_stride(), rhs)
.into_col_shape(lhs.ncols())
}
}
impl<
T: ComplexField,
Cols: Shape,
RT: (Conjugate<Canonical = T>),
RCStride: Stride,
R: (for<'a> Reborrow<'a, Target = row::Ref<'a, RT, Cols, RCStride>>),
> Mul<row::generic::Row<R>> for f64
{
type Output = Row<T, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
lhs: &T,
rhs: RowRef<'_, RT>,
) -> Row<T> {
(Scale::from_ref(lhs) * rhs.transpose()).into_transpose()
}
let lhs = &from_f64::<T>(*self);
let rhs = rhs.rb();
imp(lhs, rhs.as_dyn_cols().as_dyn_stride())
.into_col_shape(rhs.ncols())
}
}
});
impl_binop!({
impl<
T: ComplexField,
Dim: Shape,
LT: (Conjugate<Canonical = T>),
LStride: Stride,
L: (for<'a> Reborrow<'a, Target = diag::Ref<'a, LT, Dim, LStride>>),
> Mul<f64> for diag::generic::Diag<L>
{
type Output = Diag<T, Dim>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
lhs: ColRef<'_, LT>,
rhs: &T,
) -> Col<T> {
lhs * Scale::from_ref(rhs)
}
let lhs = self.rb().column_vector();
let rhs = &from_f64::<T>(*rhs);
imp(lhs.as_dyn_rows().as_dyn_stride(), rhs)
.into_row_shape(lhs.nrows())
.into_diagonal()
}
}
impl<
T: ComplexField,
Dim: Shape,
LT: (Conjugate<Canonical = T>),
LStride: Stride,
L: (for<'a> Reborrow<'a, Target = diag::Ref<'a, LT, Dim, LStride>>),
> Div<f64> for diag::generic::Diag<L>
{
type Output = Diag<T, Dim>;
fn div(self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField, LT: Conjugate<Canonical = T>>(
lhs: ColRef<'_, LT>,
rhs: &T,
) -> Col<T> {
lhs * Scale(rhs.recip())
}
let lhs = self.rb().column_vector();
let rhs = &from_f64::<T>(*rhs);
imp(lhs.as_dyn_rows().as_dyn_stride(), rhs)
.into_row_shape(lhs.nrows())
.into_diagonal()
}
}
impl<
T: ComplexField,
Dim: Shape,
RT: (Conjugate<Canonical = T>),
RStride: Stride,
R: (for<'a> Reborrow<'a, Target = diag::Ref<'a, RT, Dim, RStride>>),
> Mul<diag::generic::Diag<R>> for f64
{
type Output = Diag<T, Dim>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField, RT: Conjugate<Canonical = T>>(
lhs: &T,
rhs: ColRef<'_, RT>,
) -> Col<T> {
Scale::from_ref(lhs) * rhs
}
let lhs = &from_f64::<T>(*self);
let rhs = rhs.rb().column_vector();
imp(lhs, rhs.as_dyn_rows().as_dyn_stride())
.into_row_shape(rhs.nrows())
.into_diagonal()
}
}
});
impl_op_assign!({
impl<
T: ComplexField,
Rows: Shape,
Cols: Shape,
LRStride: Stride,
LCStride: Stride,
L: (for<'a> ReborrowMut<
'a,
Target = mat::Mut<'a, T, Rows, Cols, LRStride, LCStride>,
>),
> MulAssign<Scale<T>> for mat::generic::Mat<L>
{
fn mul_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField>(lhs: MatMut<'_, T>, rhs: &T) {
zip!(lhs).for_each(|unzip!(x)| *x *= rhs)
}
let lhs = self.rb_mut();
let rhs = &rhs.0;
imp(lhs.as_dyn_mut().as_dyn_stride_mut(), rhs)
}
}
impl<
T: ComplexField,
Rows: Shape,
Cols: Shape,
LRStride: Stride,
LCStride: Stride,
L: (for<'a> ReborrowMut<
'a,
Target = mat::Mut<'a, T, Rows, Cols, LRStride, LCStride>,
>),
> DivAssign<Scale<T>> for mat::generic::Mat<L>
{
fn div_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField>(mut lhs: MatMut<'_, T>, rhs: &T) {
lhs *= Scale(rhs.recip());
}
let lhs = self.rb_mut();
let rhs = &rhs.0;
imp(lhs.as_dyn_mut().as_dyn_stride_mut(), rhs)
}
}
});
impl_op_assign!({
impl<
T: ComplexField,
Rows: Shape,
LRStride: Stride,
L: (for<'a> ReborrowMut<'a, Target = col::Mut<'a, T, Rows, LRStride>>),
> MulAssign<Scale<T>> for col::generic::Col<L>
{
fn mul_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField>(lhs: ColMut<'_, T>, rhs: &T) {
zip!(lhs).for_each(|unzip!(x)| *x *= rhs)
}
let lhs = self.rb_mut();
let rhs = &rhs.0;
imp(lhs.as_dyn_rows_mut().as_dyn_stride_mut(), rhs)
}
}
impl<
T: ComplexField,
Rows: Shape,
LRStride: Stride,
L: (for<'a> ReborrowMut<'a, Target = col::Mut<'a, T, Rows, LRStride>>),
> DivAssign<Scale<T>> for col::generic::Col<L>
{
fn div_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField>(mut lhs: ColMut<'_, T>, rhs: &T) {
lhs *= Scale(rhs.recip());
}
let lhs = self.rb_mut();
let rhs = &rhs.0;
imp(lhs.as_dyn_rows_mut().as_dyn_stride_mut(), rhs)
}
}
});
impl_op_assign!({
impl<
T: ComplexField,
Cols: Shape,
LCStride: Stride,
L: (for<'a> ReborrowMut<'a, Target = row::Mut<'a, T, Cols, LCStride>>),
> MulAssign<Scale<T>> for row::generic::Row<L>
{
fn mul_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField>(lhs: RowMut<'_, T>, rhs: &T) {
let mut lhs = lhs.transpose_mut();
lhs *= Scale::from_ref(rhs);
}
let lhs = self.rb_mut();
let rhs = &rhs.0;
imp(lhs.as_dyn_cols_mut().as_dyn_stride_mut(), rhs)
}
}
impl<
T: ComplexField,
Cols: Shape,
LCStride: Stride,
L: (for<'a> ReborrowMut<'a, Target = row::Mut<'a, T, Cols, LCStride>>),
> DivAssign<Scale<T>> for row::generic::Row<L>
{
fn div_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField>(mut lhs: RowMut<'_, T>, rhs: &T) {
lhs *= Scale(rhs.recip());
}
let lhs = self.rb_mut();
let rhs = &rhs.0;
imp(lhs.as_dyn_cols_mut().as_dyn_stride_mut(), rhs)
}
}
});
impl_op_assign!({
impl<
T: ComplexField,
Cols: Shape,
LCStride: Stride,
L: (for<'a> ReborrowMut<'a, Target = diag::Mut<'a, T, Cols, LCStride>>),
> MulAssign<Scale<T>> for diag::generic::Diag<L>
{
fn mul_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField>(mut lhs: ColMut<'_, T>, rhs: &T) {
lhs *= Scale::from_ref(rhs);
}
let lhs = self.rb_mut().column_vector_mut();
let rhs = &rhs.0;
imp(lhs.as_dyn_rows_mut().as_dyn_stride_mut(), rhs)
}
}
impl<
T: ComplexField,
Cols: Shape,
LCStride: Stride,
L: (for<'a> ReborrowMut<'a, Target = diag::Mut<'a, T, Cols, LCStride>>),
> DivAssign<Scale<T>> for diag::generic::Diag<L>
{
fn div_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField>(mut lhs: ColMut<'_, T>, rhs: &T) {
lhs *= Scale(rhs.recip());
}
let lhs = self.rb_mut().column_vector_mut();
let rhs = &rhs.0;
imp(lhs.as_dyn_rows_mut().as_dyn_stride_mut(), rhs)
}
}
});
impl_op_assign!({
impl<
T: ComplexField,
Rows: Shape,
Cols: Shape,
LRStride: Stride,
LCStride: Stride,
L: (for<'a> ReborrowMut<
'a,
Target = mat::Mut<'a, T, Rows, Cols, LRStride, LCStride>,
>),
> MulAssign<f64> for mat::generic::Mat<L>
{
fn mul_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField>(lhs: MatMut<'_, T>, rhs: &T) {
zip!(lhs).for_each(|unzip!(x)| *x *= rhs)
}
let lhs = self.rb_mut();
let rhs = &from_f64::<T>(*rhs);
imp(lhs.as_dyn_mut().as_dyn_stride_mut(), rhs)
}
}
impl<
T: ComplexField,
Rows: Shape,
Cols: Shape,
LRStride: Stride,
LCStride: Stride,
L: (for<'a> ReborrowMut<
'a,
Target = mat::Mut<'a, T, Rows, Cols, LRStride, LCStride>,
>),
> DivAssign<f64> for mat::generic::Mat<L>
{
fn div_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField>(mut lhs: MatMut<'_, T>, rhs: &T) {
lhs *= Scale(rhs.recip());
}
let lhs = self.rb_mut();
let rhs = &from_f64::<T>(*rhs);
imp(lhs.as_dyn_mut().as_dyn_stride_mut(), rhs)
}
}
});
impl_op_assign!({
impl<
T: ComplexField,
Rows: Shape,
LRStride: Stride,
L: (for<'a> ReborrowMut<'a, Target = col::Mut<'a, T, Rows, LRStride>>),
> MulAssign<f64> for col::generic::Col<L>
{
fn mul_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField>(lhs: ColMut<'_, T>, rhs: &T) {
zip!(lhs).for_each(|unzip!(x)| *x *= rhs)
}
let lhs = self.rb_mut();
let rhs = &from_f64::<T>(*rhs);
imp(lhs.as_dyn_rows_mut().as_dyn_stride_mut(), rhs)
}
}
impl<
T: ComplexField,
Rows: Shape,
LRStride: Stride,
L: (for<'a> ReborrowMut<'a, Target = col::Mut<'a, T, Rows, LRStride>>),
> DivAssign<f64> for col::generic::Col<L>
{
fn div_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField>(mut lhs: ColMut<'_, T>, rhs: &T) {
lhs *= Scale(rhs.recip());
}
let lhs = self.rb_mut();
let rhs = &from_f64::<T>(*rhs);
imp(lhs.as_dyn_rows_mut().as_dyn_stride_mut(), rhs)
}
}
});
impl_op_assign!({
impl<
T: ComplexField,
Cols: Shape,
LCStride: Stride,
L: (for<'a> ReborrowMut<'a, Target = row::Mut<'a, T, Cols, LCStride>>),
> MulAssign<f64> for row::generic::Row<L>
{
fn mul_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField>(lhs: RowMut<'_, T>, rhs: &T) {
let mut lhs = lhs.transpose_mut();
lhs *= Scale::from_ref(rhs);
}
let lhs = self.rb_mut();
let rhs = &from_f64::<T>(*rhs);
imp(lhs.as_dyn_cols_mut().as_dyn_stride_mut(), rhs)
}
}
impl<
T: ComplexField,
Cols: Shape,
LCStride: Stride,
L: (for<'a> ReborrowMut<'a, Target = row::Mut<'a, T, Cols, LCStride>>),
> DivAssign<f64> for row::generic::Row<L>
{
fn div_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField>(mut lhs: RowMut<'_, T>, rhs: &T) {
lhs *= Scale(rhs.recip());
}
let lhs = self.rb_mut();
let rhs = &from_f64::<T>(*rhs);
imp(lhs.as_dyn_cols_mut().as_dyn_stride_mut(), rhs)
}
}
});
impl_op_assign!({
impl<
T: ComplexField,
Cols: Shape,
LCStride: Stride,
L: (for<'a> ReborrowMut<'a, Target = diag::Mut<'a, T, Cols, LCStride>>),
> MulAssign<f64> for diag::generic::Diag<L>
{
fn mul_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField>(mut lhs: ColMut<'_, T>, rhs: &T) {
lhs *= Scale::from_ref(rhs);
}
let lhs = self.rb_mut().column_vector_mut();
let rhs = &from_f64::<T>(*rhs);
imp(lhs.as_dyn_rows_mut().as_dyn_stride_mut(), rhs)
}
}
impl<
T: ComplexField,
Cols: Shape,
LCStride: Stride,
L: (for<'a> ReborrowMut<'a, Target = diag::Mut<'a, T, Cols, LCStride>>),
> DivAssign<f64> for diag::generic::Diag<L>
{
fn div_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<T: ComplexField>(mut lhs: ColMut<'_, T>, rhs: &T) {
lhs *= Scale(rhs.recip());
}
let lhs = self.rb_mut().column_vector_mut();
let rhs = &from_f64::<T>(*rhs);
imp(lhs.as_dyn_rows_mut().as_dyn_stride_mut(), rhs)
}
}
});
#[cfg(feature = "sparse")]
mod sparse {
use super::*;
use crate::internal_prelude_sp::*;
use {csc_numeric as csc, csr_numeric as csr};
impl_binop!({
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
RT: (Conjugate<Canonical = T>),
R: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, RT, Rows, Cols>>),
> Mul<csr::generic::SparseRowMat<R>> for Scale<T>
{
type Output = SparseRowMat<I, T, Rows, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
RT: Conjugate<Canonical = T>,
>(
lhs: &T,
rhs: SparseRowMatRef<'_, I, RT>,
) -> SparseRowMat<I, T> {
(Scale::from_ref(lhs) * rhs.transpose()).into_transpose()
}
let lhs = &self.0;
let rhs = rhs.rb();
imp(lhs, rhs.as_dyn()).into_shape(rhs.nrows(), rhs.ncols())
}
}
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
RT: (Conjugate<Canonical = T>),
R: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, RT, Rows, Cols>>),
> Mul<csc::generic::SparseColMat<R>> for Scale<T>
{
type Output = SparseColMat<I, T, Rows, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
RT: Conjugate<Canonical = T>,
>(
lhs: &T,
rhs: SparseColMatRef<'_, I, RT>,
) -> SparseColMat<I, T> {
with_dim!(M, rhs.nrows());
with_dim!(N, rhs.ncols());
let rhs = rhs.as_shape(M, N);
let symbolic = rhs.symbolic().to_owned().unwrap();
let mut val = alloc::vec::Vec::new();
val.resize(symbolic.row_idx().len(), zero());
for j in rhs.ncols().indices() {
for (val, rhs) in iter::zip(
&mut val[symbolic.col_range(j)],
rhs.val_of_col(j),
) {
*val = lhs * Conj::apply(rhs);
}
}
SparseColMat::new(symbolic, val).into_shape(*M, *N)
}
let lhs = &self.0;
let rhs = rhs.rb();
imp(lhs, rhs.as_dyn()).into_shape(rhs.nrows(), rhs.ncols())
}
}
});
impl_binop!({
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
L: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, LT, Rows, Cols>>),
> Mul<Scale<T>> for csr::generic::SparseRowMat<L>
{
type Output = SparseRowMat<I, T, Rows, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
>(
rhs: &T,
lhs: SparseRowMatRef<'_, I, LT>,
) -> SparseRowMat<I, T> {
(lhs.transpose() * Scale::from_ref(rhs)).into_transpose()
}
let rhs = &rhs.0;
let lhs = self.rb();
imp(rhs, lhs.as_dyn()).into_shape(lhs.nrows(), lhs.ncols())
}
}
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
L: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, LT, Rows, Cols>>),
> Mul<Scale<T>> for csc::generic::SparseColMat<L>
{
type Output = SparseColMat<I, T, Rows, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
>(
rhs: &T,
lhs: SparseColMatRef<'_, I, LT>,
) -> SparseColMat<I, T> {
with_dim!(M, lhs.nrows());
with_dim!(N, lhs.ncols());
let lhs = lhs.as_shape(M, N);
let symbolic = lhs.symbolic().to_owned().unwrap();
let mut val = alloc::vec::Vec::new();
val.resize(symbolic.row_idx().len(), zero());
for j in lhs.ncols().indices() {
for (val, lhs) in iter::zip(
&mut val[symbolic.col_range(j)],
lhs.val_of_col(j),
) {
*val = Conj::apply(lhs) * rhs;
}
}
SparseColMat::new(symbolic, val).into_shape(*M, *N)
}
let rhs = &rhs.0;
let lhs = self.rb();
imp(rhs, lhs.as_dyn()).into_shape(lhs.nrows(), lhs.ncols())
}
}
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
L: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, LT, Rows, Cols>>),
> Div<Scale<T>> for csr::generic::SparseRowMat<L>
{
type Output = SparseRowMat<I, T, Rows, Cols>;
fn div(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
>(
rhs: &T,
lhs: SparseRowMatRef<'_, I, LT>,
) -> SparseRowMat<I, T> {
lhs * Scale(rhs.recip())
}
let rhs = &rhs.0;
let lhs = self.rb();
imp(rhs, lhs.as_dyn()).into_shape(lhs.nrows(), lhs.ncols())
}
}
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
L: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, LT, Rows, Cols>>),
> Div<Scale<T>> for csc::generic::SparseColMat<L>
{
type Output = SparseColMat<I, T, Rows, Cols>;
fn div(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
>(
rhs: &T,
lhs: SparseColMatRef<'_, I, LT>,
) -> SparseColMat<I, T> {
lhs * Scale(rhs.recip())
}
let rhs = &rhs.0;
let lhs = self.rb();
imp(rhs, lhs.as_dyn()).into_shape(lhs.nrows(), lhs.ncols())
}
}
});
impl_op_assign!({
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
L: (for<'a> ReborrowMut<'a, Target = csr::Mut<'a, I, T, Rows, Cols>>),
> MulAssign<Scale<T>> for csr::generic::SparseRowMat<L>
{
fn mul_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<I: Index, T: ComplexField>(
rhs: &T,
lhs: SparseRowMatMut<'_, I, T>,
) {
let mut lhs = lhs.transpose_mut();
lhs *= Scale::from_ref(rhs);
}
let rhs = &rhs.0;
let lhs = self.rb_mut();
imp(rhs, lhs.as_dyn_mut())
}
}
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
L: (for<'a> ReborrowMut<'a, Target = csc::Mut<'a, I, T, Rows, Cols>>),
> MulAssign<Scale<T>> for csc::generic::SparseColMat<L>
{
fn mul_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<I: Index, T: ComplexField>(
rhs: &T,
lhs: SparseColMatMut<'_, I, T>,
) {
with_dim!(M, lhs.nrows());
with_dim!(N, lhs.ncols());
let mut lhs = lhs.as_shape_mut(M, N);
for j in lhs.ncols().indices() {
for val in lhs.rb_mut().val_of_col_mut(j) {
*val *= rhs;
}
}
}
let rhs = &rhs.0;
let lhs = self.rb_mut();
imp(rhs, lhs.as_dyn_mut())
}
}
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
L: (for<'a> ReborrowMut<'a, Target = csr::Mut<'a, I, T, Rows, Cols>>),
> DivAssign<Scale<T>> for csr::generic::SparseRowMat<L>
{
fn div_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<I: Index, T: ComplexField>(
rhs: &T,
lhs: SparseRowMatMut<'_, I, T>,
) {
let mut lhs = lhs.transpose_mut();
lhs /= Scale::from_ref(rhs);
}
let rhs = &rhs.0;
let lhs = self.rb_mut();
imp(rhs, lhs.as_dyn_mut())
}
}
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
L: (for<'a> ReborrowMut<'a, Target = csc::Mut<'a, I, T, Rows, Cols>>),
> DivAssign<Scale<T>> for csc::generic::SparseColMat<L>
{
fn div_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<I: Index, T: ComplexField>(
rhs: &T,
lhs: SparseColMatMut<'_, I, T>,
) {
let mut lhs = lhs.transpose_mut();
lhs *= Scale(rhs.recip());
}
let rhs = &rhs.0;
let lhs = self.rb_mut();
imp(rhs, lhs.as_dyn_mut())
}
}
});
impl_binop!({
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
RT: (Conjugate<Canonical = T>),
R: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, RT, Rows, Cols>>),
> Mul<csr::generic::SparseRowMat<R>> for f64
{
type Output = SparseRowMat<I, T, Rows, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
RT: Conjugate<Canonical = T>,
>(
lhs: &T,
rhs: SparseRowMatRef<'_, I, RT>,
) -> SparseRowMat<I, T> {
(Scale::from_ref(lhs) * rhs.transpose()).into_transpose()
}
let lhs = &from_f64::<T>(*self);
let rhs = rhs.rb();
imp(lhs, rhs.as_dyn()).into_shape(rhs.nrows(), rhs.ncols())
}
}
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
RT: (Conjugate<Canonical = T>),
R: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, RT, Rows, Cols>>),
> Mul<csc::generic::SparseColMat<R>> for f64
{
type Output = SparseColMat<I, T, Rows, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
RT: Conjugate<Canonical = T>,
>(
lhs: &T,
rhs: SparseColMatRef<'_, I, RT>,
) -> SparseColMat<I, T> {
Scale::from_ref(lhs) * rhs
}
let lhs = &from_f64::<T>(*self);
let rhs = rhs.rb();
imp(lhs, rhs.as_dyn()).into_shape(rhs.nrows(), rhs.ncols())
}
}
});
impl_binop!({
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
L: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, LT, Rows, Cols>>),
> Mul<f64> for csr::generic::SparseRowMat<L>
{
type Output = SparseRowMat<I, T, Rows, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
>(
rhs: &T,
lhs: SparseRowMatRef<'_, I, LT>,
) -> SparseRowMat<I, T> {
(lhs.transpose() * Scale::from_ref(rhs)).into_transpose()
}
let rhs = &from_f64::<T>(*rhs);
let lhs = self.rb();
imp(rhs, lhs.as_dyn()).into_shape(lhs.nrows(), lhs.ncols())
}
}
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
L: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, LT, Rows, Cols>>),
> Mul<f64> for csc::generic::SparseColMat<L>
{
type Output = SparseColMat<I, T, Rows, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
>(
rhs: &T,
lhs: SparseColMatRef<'_, I, LT>,
) -> SparseColMat<I, T> {
lhs * Scale::from_ref(rhs)
}
let rhs = &from_f64::<T>(*rhs);
let lhs = self.rb();
imp(rhs, lhs.as_dyn()).into_shape(lhs.nrows(), lhs.ncols())
}
}
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
L: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, LT, Rows, Cols>>),
> Div<f64> for csr::generic::SparseRowMat<L>
{
type Output = SparseRowMat<I, T, Rows, Cols>;
fn div(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
>(
rhs: &T,
lhs: SparseRowMatRef<'_, I, LT>,
) -> SparseRowMat<I, T> {
lhs * Scale(rhs.recip())
}
let rhs = &from_f64::<T>(*rhs);
let lhs = self.rb();
imp(rhs, lhs.as_dyn()).into_shape(lhs.nrows(), lhs.ncols())
}
}
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
L: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, LT, Rows, Cols>>),
> Div<f64> for csc::generic::SparseColMat<L>
{
type Output = SparseColMat<I, T, Rows, Cols>;
fn div(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
>(
rhs: &T,
lhs: SparseColMatRef<'_, I, LT>,
) -> SparseColMat<I, T> {
lhs * Scale(rhs.recip())
}
let rhs = &from_f64::<T>(*rhs);
let lhs = self.rb();
imp(rhs, lhs.as_dyn()).into_shape(lhs.nrows(), lhs.ncols())
}
}
});
impl_op_assign!({
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
L: (for<'a> ReborrowMut<'a, Target = csr::Mut<'a, I, T, Rows, Cols>>),
> MulAssign<f64> for csr::generic::SparseRowMat<L>
{
fn mul_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<I: Index, T: ComplexField>(
rhs: &T,
lhs: SparseRowMatMut<'_, I, T>,
) {
let mut lhs = lhs.transpose_mut();
lhs *= Scale::from_ref(rhs);
}
let rhs = &from_f64::<T>(*rhs);
let lhs = self.rb_mut();
imp(rhs, lhs.as_dyn_mut())
}
}
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
L: (for<'a> ReborrowMut<'a, Target = csc::Mut<'a, I, T, Rows, Cols>>),
> MulAssign<f64> for csc::generic::SparseColMat<L>
{
fn mul_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<I: Index, T: ComplexField>(
rhs: &T,
lhs: SparseColMatMut<'_, I, T>,
) {
*&mut { lhs } *= Scale::from_ref(rhs)
}
let rhs = &from_f64::<T>(*rhs);
let lhs = self.rb_mut();
imp(rhs, lhs.as_dyn_mut())
}
}
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
L: (for<'a> ReborrowMut<'a, Target = csr::Mut<'a, I, T, Rows, Cols>>),
> DivAssign<f64> for csr::generic::SparseRowMat<L>
{
fn div_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<I: Index, T: ComplexField>(
rhs: &T,
lhs: SparseRowMatMut<'_, I, T>,
) {
let mut lhs = lhs.transpose_mut();
lhs /= Scale::from_ref(rhs);
}
let rhs = &from_f64::<T>(*rhs);
let lhs = self.rb_mut();
imp(rhs, lhs.as_dyn_mut())
}
}
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
L: (for<'a> ReborrowMut<'a, Target = csc::Mut<'a, I, T, Rows, Cols>>),
> DivAssign<f64> for csc::generic::SparseColMat<L>
{
fn div_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<I: Index, T: ComplexField>(
rhs: &T,
lhs: SparseColMatMut<'_, I, T>,
) {
let mut lhs = lhs.transpose_mut();
lhs *= Scale(rhs.recip());
}
let rhs = &from_f64::<T>(*rhs);
let lhs = self.rb_mut();
imp(rhs, lhs.as_dyn_mut())
}
}
});
impl_op!({
impl<
I: Index,
T: Conjugate,
Rows: Shape,
Cols: Shape,
Inner: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, T, Rows, Cols>>),
> Neg for csr::generic::SparseRowMat<Inner>
{
type Output = SparseRowMat<I, T::Canonical, Rows, Cols>;
fn neg(self) {
self.rb().transpose().neg().into_transpose()
}
}
impl<
I: Index,
T: Conjugate,
Rows: Shape,
Cols: Shape,
Inner: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, T, Rows, Cols>>),
> Neg for csc::generic::SparseColMat<Inner>
{
type Output = SparseColMat<I, T::Canonical, Rows, Cols>;
fn neg(self) {
#[track_caller]
fn imp<I: Index, T: Conjugate>(
A: SparseColMatRef<'_, I, T>,
) -> SparseColMat<I, T::Canonical> {
with_dim!(M, A.nrows());
with_dim!(N, A.ncols());
let A = A.as_shape(M, N);
let symbolic = A.symbolic().to_owned().unwrap();
let mut val = alloc::vec::Vec::new();
val.resize(symbolic.row_idx().len(), zero());
for j in A.ncols().indices() {
for (val, lhs) in iter::zip(
&mut val[symbolic.col_range(j)],
A.val_of_col(j),
) {
*val = -Conj::apply(lhs);
}
}
SparseColMat::new(symbolic, val).into_shape(*M, *N)
}
let A = self.rb();
imp(A.as_dyn()).into_shape(A.nrows(), A.ncols())
}
}
});
impl_op_assign!({
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
RT: (Conjugate<Canonical = T>),
L: (for<'a> ReborrowMut<'a, Target = csc::Mut<'a, I, T, Rows, Cols>>),
R: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, RT, Rows, Cols>>),
> AddAssign<csc::generic::SparseColMat<R>> for csc::generic::SparseColMat<L>
{
fn add_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
RT: Conjugate<Canonical = T>,
>(
lhs: SparseColMatMut<'_, I, T>,
rhs: SparseColMatRef<'_, I, RT>,
) {
crate::sparse::ops::binary_op_assign_into(
lhs,
rhs,
add_assign_fn::<T, RT>,
)
}
let lhs = self.rb_mut();
let rhs = rhs.rb();
imp(lhs.as_dyn_mut(), rhs.as_dyn())
}
}
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
RT: (Conjugate<Canonical = T>),
L: (for<'a> ReborrowMut<'a, Target = csc::Mut<'a, I, T, Rows, Cols>>),
R: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, RT, Rows, Cols>>),
> SubAssign<csc::generic::SparseColMat<R>> for csc::generic::SparseColMat<L>
{
fn sub_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
RT: Conjugate<Canonical = T>,
>(
lhs: SparseColMatMut<'_, I, T>,
rhs: SparseColMatRef<'_, I, RT>,
) {
crate::sparse::ops::binary_op_assign_into(
lhs,
rhs,
sub_assign_fn::<T, RT>,
)
}
let lhs = self.rb_mut();
let rhs = rhs.rb();
imp(lhs.as_dyn_mut(), rhs.as_dyn())
}
}
});
impl_op_assign!({
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
RT: (Conjugate<Canonical = T>),
L: (for<'a> ReborrowMut<'a, Target = csr::Mut<'a, I, T, Rows, Cols>>),
R: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, RT, Rows, Cols>>),
> AddAssign<csr::generic::SparseRowMat<R>> for csr::generic::SparseRowMat<L>
{
fn add_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
RT: Conjugate<Canonical = T>,
>(
lhs: SparseRowMatMut<'_, I, T>,
rhs: SparseRowMatRef<'_, I, RT>,
) {
crate::sparse::ops::binary_op_assign_into(
lhs.transpose_mut(),
rhs.transpose(),
add_assign_fn::<T, RT>,
)
}
let lhs = self.rb_mut();
let rhs = rhs.rb();
imp(lhs.as_dyn_mut(), rhs.as_dyn())
}
}
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
RT: (Conjugate<Canonical = T>),
L: (for<'a> ReborrowMut<'a, Target = csr::Mut<'a, I, T, Rows, Cols>>),
R: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, RT, Rows, Cols>>),
> SubAssign<csr::generic::SparseRowMat<R>> for csr::generic::SparseRowMat<L>
{
fn sub_assign(&mut self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
RT: Conjugate<Canonical = T>,
>(
lhs: SparseRowMatMut<'_, I, T>,
rhs: SparseRowMatRef<'_, I, RT>,
) {
crate::sparse::ops::binary_op_assign_into(
lhs.transpose_mut(),
rhs.transpose(),
sub_assign_fn::<T, RT>,
)
}
let lhs = self.rb_mut();
let rhs = rhs.rb();
imp(lhs.as_dyn_mut(), rhs.as_dyn())
}
}
});
impl_binop!({
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
RT: (Conjugate<Canonical = T>),
L: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, LT, Rows, Cols>>),
R: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, RT, Rows, Cols>>),
> Add<csc::generic::SparseColMat<R>> for csc::generic::SparseColMat<L>
{
type Output = SparseColMat<I, T, Rows, Cols>;
fn add(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: SparseColMatRef<'_, I, LT>,
rhs: SparseColMatRef<'_, I, RT>,
) -> SparseColMat<I, T> {
crate::sparse::ops::binary_op(lhs, rhs, add_fn::<T, LT, RT>)
.unwrap()
}
let lhs = self.rb();
let rhs = rhs.rb();
let (nrows, ncols) = lhs.shape();
imp(lhs.as_dyn(), rhs.as_dyn()).into_shape(nrows, ncols)
}
}
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
RT: (Conjugate<Canonical = T>),
L: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, LT, Rows, Cols>>),
R: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, RT, Rows, Cols>>),
> Sub<csc::generic::SparseColMat<R>> for csc::generic::SparseColMat<L>
{
type Output = SparseColMat<I, T, Rows, Cols>;
fn sub(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: SparseColMatRef<'_, I, LT>,
rhs: SparseColMatRef<'_, I, RT>,
) -> SparseColMat<I, T> {
crate::sparse::ops::binary_op(lhs, rhs, sub_fn::<T, LT, RT>)
.unwrap()
}
let lhs = self.rb();
let rhs = rhs.rb();
let (nrows, ncols) = lhs.shape();
imp(lhs.as_dyn(), rhs.as_dyn()).into_shape(nrows, ncols)
}
}
});
impl_binop!({
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
RT: (Conjugate<Canonical = T>),
L: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, LT, Rows, Cols>>),
R: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, RT, Rows, Cols>>),
> Add<csr::generic::SparseRowMat<R>> for csr::generic::SparseRowMat<L>
{
type Output = SparseRowMat<I, T, Rows, Cols>;
fn add(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: SparseRowMatRef<'_, I, LT>,
rhs: SparseRowMatRef<'_, I, RT>,
) -> SparseRowMat<I, T> {
crate::sparse::ops::binary_op(
lhs.transpose(),
rhs.transpose(),
add_fn::<T, LT, RT>,
)
.unwrap()
.into_transpose()
}
let lhs = self.rb();
let rhs = rhs.rb();
let (nrows, ncols) = lhs.shape();
imp(lhs.as_dyn(), rhs.as_dyn()).into_shape(nrows, ncols)
}
}
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
LT: (Conjugate<Canonical = T>),
RT: (Conjugate<Canonical = T>),
L: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, LT, Rows, Cols>>),
R: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, RT, Rows, Cols>>),
> Sub<csr::generic::SparseRowMat<R>> for csr::generic::SparseRowMat<L>
{
type Output = SparseRowMat<I, T, Rows, Cols>;
fn sub(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: SparseRowMatRef<'_, I, LT>,
rhs: SparseRowMatRef<'_, I, RT>,
) -> SparseRowMat<I, T> {
crate::sparse::ops::binary_op(
lhs.transpose(),
rhs.transpose(),
sub_fn::<T, LT, RT>,
)
.unwrap()
.into_transpose()
}
let lhs = self.rb();
let rhs = rhs.rb();
let (nrows, ncols) = lhs.shape();
imp(lhs.as_dyn(), rhs.as_dyn()).into_shape(nrows, ncols)
}
}
});
impl_binop!({
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
Depth: Shape,
LT: (Conjugate<Canonical = T>),
RT: (Conjugate<Canonical = T>),
L: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, LT, Rows, Depth>>),
R: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, RT, Depth, Cols>>),
> Mul<csc::generic::SparseColMat<R>> for csc::generic::SparseColMat<L>
{
type Output = SparseColMat<I, T, Rows, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: SparseColMatRef<'_, I, LT>,
rhs: SparseColMatRef<'_, I, RT>,
) -> SparseColMat<I, T> {
let nrows = lhs.nrows();
let ncols = rhs.ncols();
linalg_sp::matmul::sparse_sparse_matmul(
lhs,
rhs,
one::<T>(),
crate::get_global_parallelism(),
)
.unwrap()
.into_shape(nrows, ncols)
}
let lhs = self.rb();
let rhs = rhs.rb();
let nrows = lhs.nrows();
let ncols = rhs.ncols();
imp(lhs.as_dyn(), rhs.as_dyn()).into_shape(nrows, ncols)
}
}
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
Depth: Shape,
LT: (Conjugate<Canonical = T>),
RT: (Conjugate<Canonical = T>),
L: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, LT, Rows, Depth>>),
R: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, RT, Depth, Cols>>),
> Mul<csr::generic::SparseRowMat<R>> for csr::generic::SparseRowMat<L>
{
type Output = SparseRowMat<I, T, Rows, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: SparseRowMatRef<'_, I, LT>,
rhs: SparseRowMatRef<'_, I, RT>,
) -> SparseRowMat<I, T> {
(rhs.transpose() * lhs.transpose()).into_transpose()
}
let lhs = self.rb();
let rhs = rhs.rb();
let nrows = lhs.nrows();
let ncols = rhs.ncols();
imp(lhs.as_dyn(), rhs.as_dyn()).into_shape(nrows, ncols)
}
}
});
impl_binop!({
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
Depth: Shape,
LT: (Conjugate<Canonical = T>),
RT: (Conjugate<Canonical = T>),
RRStride: Stride,
RCStride: Stride,
L: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, LT, Rows, Depth>>),
R: (for<'a> Reborrow<
'a,
Target = mat::Ref<'a, RT, Depth, Cols, RRStride, RCStride>,
>),
> Mul<mat::generic::Mat<R>> for csc::generic::SparseColMat<L>
{
type Output = Mat<T, Rows, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: SparseColMatRef<'_, I, LT>,
rhs: MatRef<'_, RT>,
) -> Mat<T> {
let nrows = lhs.nrows();
let ncols = rhs.ncols();
let mut out = Mat::zeros(nrows, ncols);
linalg_sp::matmul::sparse_dense_matmul(
out.rb_mut(),
Accum::Add,
lhs,
rhs,
T::one_impl(),
crate::get_global_parallelism(),
);
out
}
let lhs = self.rb();
let rhs = rhs.rb();
let nrows = lhs.nrows();
let ncols = rhs.ncols();
imp(lhs.as_dyn(), rhs.as_dyn().as_dyn_stride())
.into_shape(nrows, ncols)
}
}
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
Depth: Shape,
LT: (Conjugate<Canonical = T>),
RT: (Conjugate<Canonical = T>),
RRStride: Stride,
RCStride: Stride,
L: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, LT, Rows, Depth>>),
R: (for<'a> Reborrow<
'a,
Target = mat::Ref<'a, RT, Depth, Cols, RRStride, RCStride>,
>),
> Mul<mat::generic::Mat<R>> for csr::generic::SparseRowMat<L>
{
type Output = Mat<T, Rows, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: SparseRowMatRef<'_, I, LT>,
rhs: MatRef<'_, RT>,
) -> Mat<T> {
let nrows = lhs.nrows();
let ncols = rhs.ncols();
let mut out = Mat::zeros(nrows, ncols);
linalg_sp::matmul::dense_sparse_matmul(
out.rb_mut().transpose_mut(),
Accum::Add,
rhs.transpose(),
lhs.transpose(),
T::one_impl(),
crate::get_global_parallelism(),
);
out
}
let lhs = self.rb();
let rhs = rhs.rb();
let nrows = lhs.nrows();
let ncols = rhs.ncols();
imp(lhs.as_dyn(), rhs.as_dyn().as_dyn_stride())
.into_shape(nrows, ncols)
}
}
});
impl_binop!({
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Depth: Shape,
LT: (Conjugate<Canonical = T>),
RT: (Conjugate<Canonical = T>),
RRStride: Stride,
L: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, LT, Rows, Depth>>),
R: (for<'a> Reborrow<'a, Target = col::Ref<'a, RT, Depth, RRStride>>),
> Mul<col::generic::Col<R>> for csc::generic::SparseColMat<L>
{
type Output = Col<T, Rows>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: SparseColMatRef<'_, I, LT>,
rhs: ColRef<'_, RT>,
) -> Col<T> {
let nrows = lhs.nrows();
let mut out = Col::zeros(nrows);
linalg_sp::matmul::sparse_dense_matmul(
out.rb_mut().as_mat_mut(),
Accum::Add,
lhs,
rhs.as_mat(),
T::one_impl(),
crate::get_global_parallelism(),
);
out
}
let lhs = self.rb();
let rhs = rhs.rb();
let nrows = lhs.nrows();
imp(lhs.as_dyn(), rhs.as_dyn_rows().as_dyn_stride())
.into_row_shape(nrows)
}
}
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Depth: Shape,
LT: (Conjugate<Canonical = T>),
RT: (Conjugate<Canonical = T>),
RRStride: Stride,
L: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, LT, Rows, Depth>>),
R: (for<'a> Reborrow<'a, Target = col::Ref<'a, RT, Depth, RRStride>>),
> Mul<col::generic::Col<R>> for csr::generic::SparseRowMat<L>
{
type Output = Col<T, Rows>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: SparseRowMatRef<'_, I, LT>,
rhs: ColRef<'_, RT>,
) -> Col<T> {
let nrows = lhs.nrows();
let mut out = Col::zeros(nrows);
linalg_sp::matmul::dense_sparse_matmul(
out.rb_mut().transpose_mut().as_mat_mut(),
Accum::Add,
rhs.transpose().as_mat(),
lhs.transpose(),
T::one_impl(),
crate::get_global_parallelism(),
);
out
}
let lhs = self.rb();
let rhs = rhs.rb();
let nrows = lhs.nrows();
imp(lhs.as_dyn(), rhs.as_dyn_rows().as_dyn_stride())
.into_row_shape(nrows)
}
}
});
impl_binop!({
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Dim: Shape,
LT: (Conjugate<Canonical = T>),
RT: (Conjugate<Canonical = T>),
RStride: Stride,
L: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, LT, Rows, Dim>>),
R: (for<'a> Reborrow<'a, Target = diag::Ref<'a, RT, Dim, RStride>>),
> Mul<diag::generic::Diag<R>> for csc::generic::SparseColMat<L>
{
type Output = SparseColMat<I, T, Rows, Dim>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: SparseColMatRef<'_, I, LT>,
rhs: DiagRef<'_, RT>,
) -> SparseColMat<I, T> {
with_dim!(M, lhs.nrows());
with_dim!(N, lhs.ncols());
let lhs = lhs.as_shape(M, N);
let rhs = rhs.as_shape(N);
let symbolic = lhs.symbolic().to_owned().unwrap();
let mut out = alloc::vec::Vec::new();
out.resize(symbolic.row_idx().len(), T::zero_impl());
for j in lhs.ncols().indices() {
let ref rhs = Conj::apply(&rhs[j]);
for (out, lhs) in iter::zip(
&mut out[symbolic.col_range(j)],
lhs.val_of_col(j),
) {
*out = Conj::apply(lhs) * rhs;
}
}
SparseColMat::new(symbolic, out).into_shape(*M, *N)
}
let lhs = self.rb();
let rhs = rhs.rb().column_vector();
let (nrows, ncols) = lhs.shape();
imp(
lhs.as_dyn(),
rhs.as_dyn_rows().as_dyn_stride().as_diagonal(),
)
.into_shape(nrows, ncols)
}
}
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Dim: Shape,
LT: (Conjugate<Canonical = T>),
RT: (Conjugate<Canonical = T>),
RStride: Stride,
L: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, LT, Rows, Dim>>),
R: (for<'a> Reborrow<'a, Target = diag::Ref<'a, RT, Dim, RStride>>),
> Mul<diag::generic::Diag<R>> for csr::generic::SparseRowMat<L>
{
type Output = SparseRowMat<I, T, Rows, Dim>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: SparseRowMatRef<'_, I, LT>,
rhs: DiagRef<'_, RT>,
) -> SparseRowMat<I, T> {
with_dim!(M, lhs.nrows());
with_dim!(N, lhs.ncols());
let lhs = lhs.as_shape(M, N);
let rhs = rhs.as_shape(N);
let symbolic = lhs.symbolic().to_owned().unwrap();
let mut out = alloc::vec::Vec::new();
out.resize(symbolic.col_idx().len(), T::zero_impl());
for i in lhs.nrows().indices() {
for ((j, out), lhs) in iter::zip(
iter::zip(
symbolic.col_idx_of_row(i),
&mut out[symbolic.row_range(i)],
),
lhs.val_of_row(i),
) {
*out = Conj::apply(lhs) * Conj::apply(&rhs[j]);
}
}
SparseRowMat::new(symbolic, out).into_shape(*M, *N)
}
let lhs = self.rb();
let rhs = rhs.rb().column_vector();
let (nrows, ncols) = lhs.shape();
imp(
lhs.as_dyn(),
rhs.as_dyn_rows().as_dyn_stride().as_diagonal(),
)
.into_shape(nrows, ncols)
}
}
});
impl_binop!({
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Dim: Shape,
LT: (Conjugate<Canonical = T>),
L: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, LT, Rows, Dim>>),
R: (for<'a> Reborrow<'a, Target = perm::Ref<'a, I, Dim>>),
> Mul<perm::generic::Perm<R>> for csc::generic::SparseColMat<L>
{
type Output = SparseColMat<I, T, Rows, Dim>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
>(
lhs: SparseColMatRef<'_, I, LT>,
rhs: PermRef<'_, I>,
) -> SparseColMat<I, T> {
with_dim!(M, lhs.nrows());
with_dim!(N, lhs.ncols());
let lhs = lhs.as_shape(M, N);
let rhs = rhs.as_shape(N);
let symbolic = lhs.symbolic();
let mut out_col_ptr = alloc::vec::Vec::new();
let mut out_row_idx = alloc::vec::Vec::new();
let mut out = alloc::vec::Vec::new();
out_col_ptr
.resize(symbolic.col_ptr().len(), I::truncate(0));
out_row_idx
.resize(symbolic.col_ptr().len(), I::truncate(0));
out.resize(
symbolic.row_idx().len(),
T::Canonical::zero_impl(),
);
let inv = rhs.bound_arrays().1;
let mut pos = 0usize;
for j in lhs.ncols().indices() {
let inv = inv[j].zx();
let row_idx = lhs.as_dyn().row_idx_of_col_raw(*inv);
let len = row_idx.len();
out_row_idx[pos..][..len].copy_from_slice(row_idx);
for (out, lhs) in iter::zip(
&mut out[pos..][..len],
lhs.val_of_col(inv),
) {
*out = Conj::apply(lhs);
}
pos += row_idx.len();
}
out_row_idx.truncate(pos);
out.truncate(pos);
SparseColMat::new(
unsafe {
SymbolicSparseColMat::new_unchecked(
symbolic.nrows(),
symbolic.ncols(),
out_col_ptr,
None,
out_row_idx,
)
},
out,
)
.into_shape(*M, *N)
}
let lhs = self.rb();
let rhs = rhs.rb();
let (nrows, ncols) = lhs.shape();
imp(lhs.as_dyn(), rhs.as_shape(ncols.unbound()))
.into_shape(nrows, ncols)
}
}
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Dim: Shape,
LT: (Conjugate<Canonical = T>),
L: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, LT, Rows, Dim>>),
R: (for<'a> Reborrow<'a, Target = perm::Ref<'a, I, Dim>>),
> Mul<perm::generic::Perm<R>> for csr::generic::SparseRowMat<L>
{
type Output = SparseRowMat<I, T, Rows, Dim>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
>(
lhs: SparseRowMatRef<'_, I, LT>,
rhs: PermRef<'_, I>,
) -> SparseRowMat<I, T> {
with_dim!(M, lhs.nrows());
with_dim!(N, lhs.ncols());
let lhs = lhs.as_shape(M, N);
let rhs = rhs.as_shape(N);
let symbolic = lhs.symbolic();
let mut out_row_ptr = alloc::vec::Vec::new();
let mut out_col_idx = alloc::vec::Vec::new();
let mut out = alloc::vec::Vec::new();
out_row_ptr
.resize(symbolic.row_ptr().len(), I::truncate(0));
out_col_idx
.resize(symbolic.row_ptr().len(), I::truncate(0));
out.resize(
symbolic.col_idx().len(),
T::Canonical::zero_impl(),
);
let inv = rhs.bound_arrays().0;
let mut pos = 0usize;
for i in lhs.nrows().indices() {
let col_idx = lhs.col_idx_of_row_raw(i);
let len = col_idx.len();
for ((out_j, out_v), (lhs_j, lhs_v)) in iter::zip(
iter::zip(
&mut out_col_idx[pos..][..len],
&mut out[pos..][..len],
),
iter::zip(lhs.col_idx_of_row(i), lhs.val_of_row(i)),
) {
*out_j = *inv[lhs_j];
*out_v = Conj::apply(lhs_v);
}
pos += col_idx.len();
}
out_col_idx.truncate(pos);
out.truncate(pos);
SparseRowMat::new(
unsafe {
SymbolicSparseRowMat::new_unchecked(
symbolic.nrows(),
symbolic.ncols(),
out_row_ptr,
None,
out_col_idx,
)
},
out,
)
.into_shape(*M, *N)
}
let lhs = self.rb();
let rhs = rhs.rb();
let (nrows, ncols) = lhs.shape();
imp(lhs.as_dyn(), rhs.as_shape(ncols.unbound()))
.into_shape(nrows, ncols)
}
}
});
impl_binop!({
impl<
I: Index,
T: ComplexField,
Cols: Shape,
Dim: Shape,
RT: (Conjugate<Canonical = T>),
L: (for<'a> Reborrow<'a, Target = perm::Ref<'a, I, Dim>>),
R: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, RT, Dim, Cols>>),
> Mul<csc::generic::SparseColMat<R>> for perm::generic::Perm<L>
{
type Output = SparseColMat<I, T, Dim, Cols>;
fn mul(self, rhs: _) {
(rhs.rb().transpose() * self.rb().inverse()).into_transpose()
}
}
impl<
I: Index,
T: ComplexField,
Cols: Shape,
Dim: Shape,
RT: (Conjugate<Canonical = T>),
L: (for<'a> Reborrow<'a, Target = perm::Ref<'a, I, Dim>>),
R: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, RT, Dim, Cols>>),
> Mul<csr::generic::SparseRowMat<R>> for perm::generic::Perm<L>
{
type Output = SparseRowMat<I, T, Dim, Cols>;
fn mul(self, rhs: _) {
(rhs.rb().transpose() * self.rb().inverse()).into_transpose()
}
}
});
impl_binop!({
impl<
I: Index,
T: ComplexField,
Cols: Shape,
Dim: Shape,
LT: (Conjugate<Canonical = T>),
RT: (Conjugate<Canonical = T>),
LStride: Stride,
L: (for<'a> Reborrow<'a, Target = diag::Ref<'a, LT, Dim, LStride>>),
R: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, RT, Dim, Cols>>),
> Mul<csc::generic::SparseColMat<R>> for diag::generic::Diag<L>
{
type Output = SparseColMat<I, T, Dim, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: DiagRef<'_, LT>,
rhs: SparseColMatRef<'_, I, RT>,
) -> SparseColMat<I, T> {
(rhs.transpose() * lhs).into_transpose()
}
let lhs = self.rb().column_vector();
let rhs = rhs.rb();
let (nrows, ncols) = rhs.shape();
imp(
lhs.as_dyn_rows().as_dyn_stride().as_diagonal(),
rhs.as_dyn(),
)
.into_shape(nrows, ncols)
}
}
impl<
I: Index,
T: ComplexField,
Cols: Shape,
Dim: Shape,
LT: (Conjugate<Canonical = T>),
RT: (Conjugate<Canonical = T>),
LStride: Stride,
L: (for<'a> Reborrow<'a, Target = diag::Ref<'a, LT, Dim, LStride>>),
R: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, RT, Dim, Cols>>),
> Mul<csr::generic::SparseRowMat<R>> for diag::generic::Diag<L>
{
type Output = SparseRowMat<I, T, Dim, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: DiagRef<'_, LT>,
rhs: SparseRowMatRef<'_, I, RT>,
) -> SparseRowMat<I, T> {
(rhs.transpose() * lhs).into_transpose()
}
let lhs = self.rb().column_vector();
let rhs = rhs.rb();
let (nrows, ncols) = rhs.shape();
imp(
lhs.as_dyn_rows().as_dyn_stride().as_diagonal(),
rhs.as_dyn(),
)
.into_shape(nrows, ncols)
}
}
});
impl_binop!({
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
Depth: Shape,
LT: (Conjugate<Canonical = T>),
LRStride: Stride,
LCStride: Stride,
RT: (Conjugate<Canonical = T>),
L: (for<'a> Reborrow<
'a,
Target = mat::Ref<'a, LT, Rows, Depth, LRStride, LCStride>,
>),
R: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, RT, Depth, Cols>>),
> Mul<csc::generic::SparseColMat<R>> for mat::generic::Mat<L>
{
type Output = Mat<T, Rows, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: MatRef<'_, LT>,
rhs: SparseColMatRef<'_, I, RT>,
) -> Mat<T> {
let nrows = lhs.nrows();
let ncols = rhs.ncols();
let mut out = Mat::zeros(nrows, ncols);
linalg_sp::matmul::dense_sparse_matmul(
out.rb_mut(),
Accum::Add,
lhs,
rhs,
T::one_impl(),
crate::get_global_parallelism(),
);
out
}
let lhs = self.rb();
let rhs = rhs.rb();
let nrows = lhs.nrows();
let ncols = rhs.ncols();
imp(lhs.as_dyn().as_dyn_stride(), rhs.as_dyn())
.into_shape(nrows, ncols)
}
}
impl<
I: Index,
T: ComplexField,
Rows: Shape,
Cols: Shape,
Depth: Shape,
LT: (Conjugate<Canonical = T>),
LRStride: Stride,
LCStride: Stride,
RT: (Conjugate<Canonical = T>),
L: (for<'a> Reborrow<
'a,
Target = mat::Ref<'a, LT, Rows, Depth, LRStride, LCStride>,
>),
R: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, RT, Depth, Cols>>),
> Mul<csr::generic::SparseRowMat<R>> for mat::generic::Mat<L>
{
type Output = Mat<T, Rows, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: MatRef<'_, LT>,
rhs: SparseRowMatRef<'_, I, RT>,
) -> Mat<T> {
let nrows = lhs.nrows();
let ncols = rhs.ncols();
let mut out = Mat::zeros(nrows, ncols);
linalg_sp::matmul::sparse_dense_matmul(
out.rb_mut().transpose_mut(),
Accum::Add,
rhs.transpose(),
lhs.transpose(),
T::one_impl(),
crate::get_global_parallelism(),
);
out
}
let lhs = self.rb();
let rhs = rhs.rb();
let nrows = lhs.nrows();
let ncols = rhs.ncols();
imp(lhs.as_dyn().as_dyn_stride(), rhs.as_dyn())
.into_shape(nrows, ncols)
}
}
});
impl_binop!({
impl<
I: Index,
T: ComplexField,
Cols: Shape,
Depth: Shape,
LT: (Conjugate<Canonical = T>),
LCStride: Stride,
RT: (Conjugate<Canonical = T>),
L: (for<'a> Reborrow<'a, Target = row::Ref<'a, LT, Depth, LCStride>>),
R: (for<'a> Reborrow<'a, Target = csc::Ref<'a, I, RT, Depth, Cols>>),
> Mul<csc::generic::SparseColMat<R>> for row::generic::Row<L>
{
type Output = Row<T, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: RowRef<'_, LT>,
rhs: SparseColMatRef<'_, I, RT>,
) -> Row<T> {
let ncols = rhs.ncols();
let mut out = Row::zeros(ncols);
linalg_sp::matmul::dense_sparse_matmul(
out.rb_mut().as_mat_mut(),
Accum::Add,
lhs.as_mat(),
rhs,
T::one_impl(),
crate::get_global_parallelism(),
);
out
}
let lhs = self.rb();
let rhs = rhs.rb();
let ncols = rhs.ncols();
imp(lhs.as_dyn_cols().as_dyn_stride(), rhs.as_dyn())
.into_col_shape(ncols)
}
}
impl<
I: Index,
T: ComplexField,
Cols: Shape,
Depth: Shape,
LT: (Conjugate<Canonical = T>),
LCStride: Stride,
RT: (Conjugate<Canonical = T>),
L: (for<'a> Reborrow<'a, Target = row::Ref<'a, LT, Depth, LCStride>>),
R: (for<'a> Reborrow<'a, Target = csr::Ref<'a, I, RT, Depth, Cols>>),
> Mul<csr::generic::SparseRowMat<R>> for row::generic::Row<L>
{
type Output = Row<T, Cols>;
fn mul(self, rhs: _) {
#[track_caller]
fn imp<
I: Index,
T: ComplexField,
LT: Conjugate<Canonical = T>,
RT: Conjugate<Canonical = T>,
>(
lhs: RowRef<'_, LT>,
rhs: SparseRowMatRef<'_, I, RT>,
) -> Row<T> {
let ncols = rhs.ncols();
let mut out = Row::zeros(ncols);
linalg_sp::matmul::sparse_dense_matmul(
out.rb_mut().transpose_mut().as_mat_mut(),
Accum::Add,
rhs.transpose(),
lhs.transpose().as_mat(),
T::one_impl(),
crate::get_global_parallelism(),
);
out
}
let lhs = self.rb();
let rhs = rhs.rb();
let ncols = rhs.ncols();
imp(lhs.as_dyn_cols().as_dyn_stride(), rhs.as_dyn())
.into_col_shape(ncols)
}
}
});
fn add_fn<
T: ComplexField,
LhsT: Conjugate<Canonical = T>,
RhsT: Conjugate<Canonical = T>,
>(
lhs: Option<&LhsT>,
rhs: Option<&RhsT>,
) -> T {
lhs.map(Conj::apply).unwrap_or_else(zero::<T>)
+ rhs.map(Conj::apply).unwrap_or_else(zero::<T>)
}
fn sub_fn<
T: ComplexField,
LhsT: Conjugate<Canonical = T>,
RhsT: Conjugate<Canonical = T>,
>(
lhs: Option<&LhsT>,
rhs: Option<&RhsT>,
) -> T {
lhs.map(Conj::apply).unwrap_or_else(zero::<T>)
- rhs.map(Conj::apply).unwrap_or_else(zero::<T>)
}
fn add_assign_fn<T: ComplexField, RhsT: Conjugate<Canonical = T>>(
dst: &mut T,
rhs: Option<&RhsT>,
) {
if let Some(rhs) = rhs {
*dst += Conj::apply(rhs);
}
}
fn sub_assign_fn<T: ComplexField, RhsT: Conjugate<Canonical = T>>(
dst: &mut T,
rhs: Option<&RhsT>,
) {
if let Some(rhs) = rhs {
*dst -= Conj::apply(rhs);
}
}
}
#[cfg(test)]
#[allow(non_snake_case)]
mod test {
use crate::assert;
use crate::col::*;
use crate::internal_prelude::*;
use crate::mat::*;
use crate::perm::*;
use crate::row::*;
use assert_approx_eq::assert_approx_eq;
fn matrices() -> (Mat<f64>, Mat<f64>) {
let A = mat![[2.8, -3.3], [-1.7, 5.2], [4.6, -8.3],];
let B = mat![[-7.9, 8.3], [4.7, -3.2], [3.8, -5.2],];
(A, B)
}
fn rows() -> (Row<f64>, Row<f64>) {
(row![2.8, -3.3], row![-7.9, 8.3])
}
fn cols() -> (Col<f64>, Col<f64>) {
(col![2.8, -3.3], col![-7.9, 8.3])
}
#[test]
#[should_panic]
fn test_adding_matrices_of_different_sizes_should_panic() {
let A = mat![[1.0, 2.0], [3.0, 4.0]];
let B = mat![[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]];
_ = A + B;
}
#[test]
#[should_panic]
fn test_subtracting_two_matrices_of_different_sizes_should_panic() {
let A = mat![[1.0, 2.0], [3.0, 4.0]];
let B = mat![[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]];
_ = A - B;
}
#[test]
fn test_matrix_add() {
let (A, B) = matrices();
let expected = mat![[-5.1, 5.0], [3.0, 2.0], [8.4, -13.5],];
assert_matrix_approx_eq(A.as_ref() + B.as_ref(), &expected);
assert_matrix_approx_eq(&A + &B, &expected);
assert_matrix_approx_eq(A.as_ref() + &B, &expected);
assert_matrix_approx_eq(&A + B.as_ref(), &expected);
assert_matrix_approx_eq(A.as_ref() + B.clone(), &expected);
assert_matrix_approx_eq(&A + B.clone(), &expected);
assert_matrix_approx_eq(A.clone() + B.as_ref(), &expected);
assert_matrix_approx_eq(A.clone() + &B, &expected);
assert_matrix_approx_eq(A + B, &expected);
}
#[test]
fn test_row_add() {
let (A, B) = rows();
let expected = row![-5.1, 5.0];
assert_row_approx_eq(A.as_ref() + B.as_ref(), &expected);
assert_row_approx_eq(&A + &B, &expected);
assert_row_approx_eq(A.as_ref() + &B, &expected);
assert_row_approx_eq(&A + B.as_ref(), &expected);
assert_row_approx_eq(A.as_ref() + B.clone(), &expected);
assert_row_approx_eq(A.clone() + B.as_ref(), &expected);
assert_row_approx_eq(&A + B.clone(), &expected);
assert_row_approx_eq(A.clone() + &B, &expected);
assert_row_approx_eq(A + B, &expected);
}
#[test]
fn test_col_add() {
let (A, B) = cols();
let expected = col![-5.1, 5.0];
assert_col_approx_eq(A.as_ref() + B.as_ref(), &expected);
assert_col_approx_eq(&A + &B, &expected);
assert_col_approx_eq(A.as_ref() + &B, &expected);
assert_col_approx_eq(&A + B.as_ref(), &expected);
assert_col_approx_eq(A.as_ref() + B.clone(), &expected);
assert_col_approx_eq(A.clone() + B.as_ref(), &expected);
assert_col_approx_eq(&A + B.clone(), &expected);
assert_col_approx_eq(A.clone() + &B, &expected);
assert_col_approx_eq(A + B, &expected);
}
#[test]
fn test_matrix_sub() {
let (A, B) = matrices();
let expected = mat![[10.7, -11.6], [-6.4, 8.4], [0.8, -3.1],];
assert_matrix_approx_eq(A.as_ref() - B.as_ref(), &expected);
assert_matrix_approx_eq(&A - &B, &expected);
assert_matrix_approx_eq(A.as_ref() - &B, &expected);
assert_matrix_approx_eq(&A - B.as_ref(), &expected);
assert_matrix_approx_eq(A.as_ref() - B.clone(), &expected);
assert_matrix_approx_eq(&A - B.clone(), &expected);
assert_matrix_approx_eq(A.clone() - B.as_ref(), &expected);
assert_matrix_approx_eq(A.clone() - &B, &expected);
assert_matrix_approx_eq(A - B, &expected);
}
#[test]
fn test_row_sub() {
let (A, B) = rows();
let expected = row![10.7, -11.6];
assert_row_approx_eq(A.as_ref() - B.as_ref(), &expected);
assert_row_approx_eq(&A - &B, &expected);
assert_row_approx_eq(A.as_ref() - &B, &expected);
assert_row_approx_eq(&A - B.as_ref(), &expected);
assert_row_approx_eq(A.as_ref() - B.clone(), &expected);
assert_row_approx_eq(A.clone() - B.as_ref(), &expected);
assert_row_approx_eq(&A - B.clone(), &expected);
assert_row_approx_eq(A.clone() - &B, &expected);
assert_row_approx_eq(A - B, &expected);
}
#[test]
fn test_col_sub() {
let (A, B) = cols();
let expected = col![10.7, -11.6];
assert_col_approx_eq(A.as_ref() - B.as_ref(), &expected);
assert_col_approx_eq(&A - &B, &expected);
assert_col_approx_eq(A.as_ref() - &B, &expected);
assert_col_approx_eq(&A - B.as_ref(), &expected);
assert_col_approx_eq(A.as_ref() - B.clone(), &expected);
assert_col_approx_eq(A.clone() - B.as_ref(), &expected);
assert_col_approx_eq(&A - B.clone(), &expected);
assert_col_approx_eq(A.clone() - &B, &expected);
assert_col_approx_eq(A - B, &expected);
}
#[test]
fn test_neg() {
let (A, _) = matrices();
let expected = mat![[-2.8, 3.3], [1.7, -5.2], [-4.6, 8.3],];
assert!(-A == expected);
}
#[test]
fn test_scalar_mul() {
use crate::Scale as scale;
let (A, _) = matrices();
let k = 3.0;
let expected =
Mat::from_fn(A.nrows(), A.ncols(), |i, j| A.as_ref()[(i, j)] * k);
{
assert_matrix_approx_eq(A.as_ref() * scale(k), &expected);
assert_matrix_approx_eq(&A * scale(k), &expected);
assert_matrix_approx_eq(A.as_ref() * scale(k), &expected);
assert_matrix_approx_eq(&A * scale(k), &expected);
assert_matrix_approx_eq(A.as_ref() * scale(k), &expected);
assert_matrix_approx_eq(&A * scale(k), &expected);
assert_matrix_approx_eq(A.clone() * scale(k), &expected);
assert_matrix_approx_eq(A.clone() * scale(k), &expected);
assert_matrix_approx_eq(A * scale(k), &expected);
}
let (A, _) = matrices();
{
assert_matrix_approx_eq(scale(k) * A.as_ref(), &expected);
assert_matrix_approx_eq(scale(k) * &A, &expected);
assert_matrix_approx_eq(scale(k) * A.as_ref(), &expected);
assert_matrix_approx_eq(scale(k) * &A, &expected);
assert_matrix_approx_eq(scale(k) * A.as_ref(), &expected);
assert_matrix_approx_eq(scale(k) * &A, &expected);
assert_matrix_approx_eq(scale(k) * A.clone(), &expected);
assert_matrix_approx_eq(scale(k) * A.clone(), &expected);
assert_matrix_approx_eq(scale(k) * A, &expected);
}
}
#[test]
fn test_diag_mul() {
let (A, _) = matrices();
let diag_left = mat![[1.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 3.0]];
let diag_right = mat![[4.0, 0.0], [0.0, 5.0]];
assert!(&diag_left * &A == diag_left.as_ref().diagonal() * &A);
assert!(&A * &diag_right == &A * diag_right.as_ref().diagonal());
}
#[test]
fn test_perm_mul() {
let A = Mat::from_fn(6, 5, |i, j| (j + 5 * i) as f64);
let pl = Perm::<usize>::new_checked(
Box::new([5, 1, 4, 0, 2, 3]),
Box::new([3, 1, 4, 5, 2, 0]),
6,
);
let pr = Perm::<usize>::new_checked(
Box::new([1, 4, 0, 2, 3]),
Box::new([2, 0, 3, 4, 1]),
5,
);
let perm_left = mat![
[0.0, 0.0, 0.0, 0.0, 0.0, 1.0],
[0.0, 1.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 1.0, 0.0],
[1.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 1.0, 0.0, 0.0],
];
let perm_right = mat![
[0.0, 1.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 1.0],
[1.0, 0.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 1.0, 0.0],
];
assert!(
&pl * pl.as_ref().inverse()
== PermRef::<'_, usize>::new_checked(
&[0, 1, 2, 3, 4, 5],
&[0, 1, 2, 3, 4, 5],
6
)
);
assert!(&perm_left * &A == &pl * &A);
assert!(&A * &perm_right == &A * &pr);
}
#[test]
fn test_matmul_col_row() {
let A = Col::from_fn(6, |i| i as f64);
let B = Row::from_fn(6, |j| (5 * j + 1) as f64);
assert!(&A * &B == A.as_mat() * B.as_mat());
assert!(&B * &A == (B.as_mat() * A.as_mat())[(0, 0)],);
}
fn assert_row_approx_eq(given: Row<f64>, expected: &Row<f64>) {
assert_eq!(given.nrows(), expected.nrows());
for i in 0..given.nrows() {
assert_approx_eq!(given.as_ref()[i], expected.as_ref()[i]);
}
}
fn assert_col_approx_eq(given: Col<f64>, expected: &Col<f64>) {
assert_eq!(given.ncols(), expected.ncols());
for i in 0..given.ncols() {
assert_approx_eq!(given.as_ref()[i], expected.as_ref()[i]);
}
}
fn assert_matrix_approx_eq(given: Mat<f64>, expected: &Mat<f64>) {
assert_eq!(given.nrows(), expected.nrows());
assert_eq!(given.ncols(), expected.ncols());
for i in 0..given.nrows() {
for j in 0..given.ncols() {
assert_approx_eq!(
given.as_ref()[(i, j)],
expected.as_ref()[(i, j)]
);
}
}
}
}