use dyn_stack::{MemStack, StackReq};
use faer::sparse::linalg::matmul::sparse_dense_matmul;
use faer::{Accum, MatMut, MatRef, Par};
use faer_traits::math_utils::{one, zero};
use faer_traits::{ComplexField, Index};
use super::Fsai;
pub(crate) fn apply_out<I, T>(
fsai: &Fsai<I, T>,
mut out: MatMut<'_, T>,
rhs: MatRef<'_, T>,
conjugate: bool,
par: Par,
stack: &mut MemStack,
) where
I: Index,
T: ComplexField,
{
let n = fsai.dim;
let ncols = rhs.ncols();
let (mut ybuf, _) = stack.make_with::<T>(n * ncols, |_| zero::<T>());
let mut y = MatMut::from_column_major_slice_mut(&mut ybuf[..], n, ncols);
let g = fsai.g_view();
if !conjugate {
sparse_dense_matmul(y.as_mut(), Accum::Replace, g, rhs, one::<T>(), par);
sparse_dense_matmul(out.as_mut(), Accum::Replace, g.adjoint(), y.as_ref(), one::<T>(), par);
} else {
sparse_dense_matmul(y.as_mut(), Accum::Replace, g.conjugate(), rhs, one::<T>(), par);
sparse_dense_matmul(out.as_mut(), Accum::Replace, g.transpose(), y.as_ref(), one::<T>(), par);
}
}
pub(crate) fn apply_inplace<I, T>(
fsai: &Fsai<I, T>,
mut rhs: MatMut<'_, T>,
conjugate: bool,
par: Par,
stack: &mut MemStack,
) where
I: Index,
T: ComplexField,
{
let n = fsai.dim;
let ncols = rhs.ncols();
let (mut ybuf, _) = stack.make_with::<T>(n * ncols, |_| zero::<T>());
let mut y = MatMut::from_column_major_slice_mut(&mut ybuf[..], n, ncols);
let g = fsai.g_view();
if !conjugate {
sparse_dense_matmul(y.as_mut(), Accum::Replace, g, rhs.as_ref(), one::<T>(), par);
sparse_dense_matmul(rhs.as_mut(), Accum::Replace, g.adjoint(), y.as_ref(), one::<T>(), par);
} else {
sparse_dense_matmul(y.as_mut(), Accum::Replace, g.conjugate(), rhs.as_ref(), one::<T>(), par);
sparse_dense_matmul(rhs.as_mut(), Accum::Replace, g.transpose(), y.as_ref(), one::<T>(), par);
}
}
pub(crate) fn scratch<I, T: ComplexField>(fsai: &Fsai<I, T>, ncols: usize) -> StackReq {
StackReq::new::<T>(fsai.dim * ncols)
}