use num_traits::{Zero, One};
use core::marker::PhantomData;
use crate::solver::{Cone, LinAlg, SliceLike};
pub struct ConeSOC<L: LinAlg>
{
ph_l: PhantomData<L>,
}
impl<L: LinAlg> ConeSOC<L>
{
pub fn new() -> Self
{
ConeSOC {
ph_l: PhantomData,
}
}
}
impl<L: LinAlg> Cone<L> for ConeSOC<L>
{
fn proj(&mut self, _dual_cone: bool, x: &mut L::Sl) -> Result<(), ()>
{
let f0 = L::F::zero();
let f1 = L::F::one();
let f2 = f1 + f1;
if x.len() > 0 {
let (mut s, mut v) = x.split_mut(1);
let val_s = s.get(0);
let norm_v = L::norm(&v);
if norm_v <= -val_s {
L::scale(f0, &mut v);
s.set(0, f0);
}
else if norm_v <= val_s {
}
else {
let alpha = (f1 + val_s / norm_v) / f2;
L::scale(alpha, &mut v);
s.set(0, (norm_v + val_s) / f2);
}
}
Ok(())
}
fn product_group<G: Fn(&mut L::Sl) + Copy>(&self, dp_tau: &mut L::Sl, group: G)
{
group(dp_tau);
}
}