use crate::blu::BLU;
use crate::LUInt;
use crate::Status;
pub fn maxvolume(
obj: &mut BLU,
ncol: usize,
a_p: &[usize],
a_i: &[usize],
a_x: &[f64],
basis: &mut [LUInt],
isbasic: &mut [LUInt],
volumetol: f64,
p_nupdate: Option<&mut LUInt>,
) -> Status {
let mut nupdate = 0;
if volumetol < 1.0 {
let status = Status::ErrorInvalidArgument;
if let Some(p_nupdate) = p_nupdate {
*p_nupdate = nupdate;
}
return status;
}
let mut status = factorize(obj, a_p, a_i, a_x, basis);
if status != Status::OK {
if let Some(p_nupdate) = p_nupdate {
*p_nupdate = nupdate;
}
return status;
}
for j in 0..ncol {
if isbasic[j as usize] != 0 {
continue;
}
let nzrhs = a_p[(j + 1) as usize] - a_p[j as usize];
let begin = a_p[j as usize] as usize;
status = obj.solve_for_update(nzrhs, &a_i[begin..], Some(&a_x[begin..]), 'N', 1);
if status != Status::OK {
if let Some(p_nupdate) = p_nupdate {
*p_nupdate = nupdate;
}
return status;
}
let mut xmax = 0.0;
let mut xtbl = 0.0;
let mut imax = 0;
for k in 0..obj.nzlhs {
let i = obj.ilhs[k as usize] as usize;
if obj.lhs[i].abs() > xmax {
xtbl = obj.lhs[i];
xmax = xtbl.abs();
imax = i;
}
}
let imax_vec = vec![imax];
if xmax <= volumetol {
continue;
}
isbasic[basis[imax as usize] as usize] = 0;
isbasic[j as usize] = 1;
basis[imax as usize] = j as LUInt;
nupdate += 1;
status = obj.solve_for_update(0, &imax_vec, None, 'T', 0);
if status != Status::OK {
if let Some(p_nupdate) = p_nupdate {
*p_nupdate = nupdate;
}
return status;
}
status = obj.update(xtbl);
if status != Status::OK {
if let Some(p_nupdate) = p_nupdate {
*p_nupdate = nupdate;
}
return status;
}
status = refactorize_if_needed(obj, a_p, a_i, a_x, basis);
if status != Status::OK {
if let Some(p_nupdate) = p_nupdate {
*p_nupdate = nupdate;
}
return status;
}
}
if let Some(p_nupdate) = p_nupdate {
*p_nupdate = nupdate;
}
status
}
fn factorize(obj: &mut BLU, a_p: &[usize], a_i: &[usize], a_x: &[f64], basis: &[LUInt]) -> Status {
let m = obj.lu.m as usize;
let mut begin = vec![0; m];
let mut end = vec![0; m];
for i in 0..m {
begin[i] = a_p[basis[i] as usize];
end[i] = a_p[basis[i] as usize + 1];
}
obj.factorize(&begin, &end, a_i, a_x)
}
fn refactorize_if_needed(
obj: &mut BLU,
a_p: &[usize],
a_i: &[usize],
a_x: &[f64],
basis: &[LUInt],
) -> Status {
let mut status = Status::OK;
let piverr_tol = 1e-8;
if obj.lu.nforrest == obj.lu.m || obj.lu.pivot_error > piverr_tol || obj.lu.update_cost() > 1.0
{
status = factorize(obj, a_p, a_i, a_x, basis);
}
status
}