use crate::algebra::{FloatT, MatrixShape, VectorMath};
pub trait SymmetricCone<T: FloatT>: JordanAlgebra<T> {
fn add_scaled_e(&self, x: &mut [T], α: T);
fn mul_W(&self, is_transpose: MatrixShape, y: &mut [T], x: &[T], α: T, β: T);
fn mul_Winv(&self, is_transpose: MatrixShape, y: &mut [T], x: &[T], α: T, β: T);
fn λ_inv_circ_op(&self, x: &mut [T], z: &[T]);
}
pub trait JordanAlgebra<T: FloatT> {
fn circ_op(&self, x: &mut [T], y: &[T], z: &[T]);
fn inv_circ_op(&self, x: &mut [T], y: &[T], z: &[T]);
}
pub(super) trait SymmetricConeUtils<T: FloatT> {
fn _combined_ds_shift_symmetric(
&self,
shift: &mut [T],
step_z: &mut [T],
step_s: &mut [T],
σμ: T,
);
fn _Δs_from_Δz_offset_symmetric(&self, out: &mut [T], ds: &[T], work: &mut [T]);
}
impl<T, C> SymmetricConeUtils<T> for C
where
T: FloatT,
C: SymmetricCone<T>,
{
fn _combined_ds_shift_symmetric(
&self,
shift: &mut [T],
step_z: &mut [T],
step_s: &mut [T],
σμ: T,
) {
let tmp = shift;
tmp.copy_from(step_z);
self.mul_W(MatrixShape::N, step_z, tmp, T::one(), T::zero());
tmp.copy_from(step_s);
self.mul_Winv(MatrixShape::T, step_s, tmp, T::one(), T::zero());
let shift = tmp;
self.circ_op(shift, step_s, step_z);
self.add_scaled_e(shift, -σμ);
}
fn _Δs_from_Δz_offset_symmetric(&self, out: &mut [T], ds: &[T], work: &mut [T]) {
self.λ_inv_circ_op(work, ds);
self.mul_W(MatrixShape::T, out, work, T::one(), T::zero());
}
}