use crate::lu::file::{file_diff, file_empty};
use crate::lu::list::{list_add, list_init, list_move};
use crate::lu::LU;
use crate::LUInt;
use crate::Status;
macro_rules! w_begin2 {
($lu:ident) => {
$lu.w_begin[($lu.m as usize)..]
};
}
macro_rules! w_end2 {
($lu:ident) => {
$lu.w_end[($lu.m as usize)..]
};
}
pub(crate) fn setup_bump(
lu: &mut LU,
b_begin: &[usize],
b_end: &[usize],
b_i: &[usize],
b_x: &[f64],
) -> Status {
let m = lu.m;
let rank = lu.rank;
let w_mem = lu.w_mem;
let b_nz = lu.matrix_nz;
let l_nz = lu.l_begin_p[rank as usize] as usize - rank;
let u_nz = lu.u_begin[rank as usize] as usize;
let abstol = lu.abstol;
let pad = lu.pad;
let stretch = lu.stretch;
let colcount_flink = &mut lu.colcount_flink;
let colcount_blink = &mut lu.colcount_blink;
let rowcount_flink = &mut lu.rowcount_flink;
let rowcount_blink = &mut lu.rowcount_blink;
let pinv = &lu.pinv;
let qinv = &lu.qinv;
let w_flink = &mut lu.w_flink;
let w_blink = &mut lu.w_blink;
let w_index = &mut lu.w_index;
let w_value = &mut lu.w_value;
let colmax = &mut lu.col_pivot;
let iwork0 = &mut lu.iwork0;
let mut bump_nz = b_nz - l_nz - u_nz - rank;
let mut min_rownz = 0;
let mut min_colnz = 0;
#[cfg(feature = "debug")]
for i in 0..m {
assert_eq!(iwork0[i], 0);
}
let need = bump_nz + (stretch * bump_nz as f64) as usize + (m - rank) * pad;
let need = 2 * need; if need > w_mem {
lu.addmem_w = need - w_mem;
return Status::Reallocate;
}
file_empty(
2 * m,
&mut lu.w_begin,
&mut lu.w_end,
w_flink,
w_blink,
w_mem as LUInt,
);
list_init(
colcount_flink,
colcount_blink,
m,
m + 2,
Some(&mut min_colnz),
);
let mut put: usize = 0;
for j in 0..m {
if qinv[j as usize] >= 0 {
continue;
}
let mut cnz = 0; let mut cmx = 0.0; for pos in b_begin[j as usize]..b_end[j as usize] {
let i = b_i[pos as usize] as usize;
if pinv[i] >= 0 {
continue;
}
cmx = f64::max(cmx, b_x[pos as usize].abs());
cnz += 1;
}
if cmx == 0.0 || cmx < abstol {
colmax[j as usize] = 0.0;
list_add(
j,
0,
colcount_flink,
colcount_blink,
m,
Some(&mut min_colnz),
);
bump_nz -= cnz;
} else {
colmax[j as usize] = cmx;
list_add(
j,
cnz,
colcount_flink,
colcount_blink,
m,
Some(&mut min_colnz),
);
lu.w_begin[j as usize] = put as LUInt;
for pos in b_begin[j as usize]..b_end[j as usize] {
let i = b_i[pos as usize];
if pinv[i as usize] >= 0 {
continue;
}
w_index[put] = i as LUInt;
w_value[put] = b_x[pos as usize];
put += 1;
iwork0[i as usize] += 1;
}
lu.w_end[j as usize] = put as LUInt;
put += (stretch * cnz as f64) as usize + pad;
list_move(j, 0, w_flink, w_blink, 2 * m, None);
}
}
list_init(
rowcount_flink,
rowcount_blink,
m,
m + 2,
Some(&mut min_rownz),
);
for i in 0..m {
if pinv[i as usize] >= 0 {
continue;
}
let rnz = iwork0[i as usize] as usize;
iwork0[i as usize] = 0;
list_add(
i,
rnz,
rowcount_flink,
rowcount_blink,
m,
Some(&mut min_rownz),
);
w_begin2![lu][i as usize] = put as LUInt;
w_end2![lu][i as usize] = put as LUInt;
put += rnz;
list_move(m + i, 0, w_flink, w_blink, 2 * m, None);
put += (stretch * rnz as f64) as usize + pad;
}
for j in 0..m {
for pos in lu.w_begin[j as usize]..lu.w_end[j as usize] {
let i = w_index[pos as usize] as usize;
w_index[w_end2![lu][i] as usize] = j as LUInt;
w_end2![lu][i] += 1;
}
}
lu.w_begin[(2 * m) as usize] = put as LUInt; assert!(lu.w_begin[(2 * m) as usize] <= lu.w_end[(2 * m) as usize]);
assert_eq!(
file_diff(
m,
&lu.w_begin,
&lu.w_end,
&w_begin2!(lu),
&w_end2!(lu),
w_index,
None
),
0
);
assert_eq!(
file_diff(
m,
&w_begin2!(lu),
&w_end2!(lu),
&lu.w_begin,
&lu.w_end,
w_index,
None
),
0
);
#[cfg(feature = "debug")]
for i in 0..m {
assert_eq!(iwork0[i], 0);
}
lu.bump_nz = bump_nz;
lu.bump_size = m - rank;
lu.min_colnz = min_colnz;
lu.min_rownz = min_rownz;
Status::OK
}