use crate::core::math::Scalar;
pub(crate) struct ModelWork<F> {
pub(crate) g: Vec<F>,
pub(crate) a: Vec<F>,
pub(crate) b: Vec<F>,
difference: Vec<F>,
}
impl<F: Scalar> ModelWork<F> {
pub(crate) fn new(n: usize, m: usize) -> Self {
Self {
g: vec![F::zero(); n],
a: vec![F::zero(); n * m],
b: vec![F::zero(); m],
difference: vec![F::zero(); n],
}
}
pub(crate) fn build(&mut self, fval: &[F], conmat: &[F], simi: &[F]) {
let n = self.g.len();
let m = self.b.len();
build_g_into(fval, simi, n, &mut self.g);
build_a_into(conmat, simi, n, m, &mut self.a, &mut self.difference);
for i in 0..m {
self.b[i] = -conmat[i + n * m];
}
}
}
fn build_g_into<F: Scalar>(fval: &[F], simi: &[F], n: usize, g: &mut [F]) {
let fn_pole = fval[n];
for l in 0..n {
g[l] = (0..n).map(|i| (fval[i] - fn_pole) * simi[i + l * n]).sum();
}
}
fn build_a_into<F: Scalar>(
conmat: &[F],
simi: &[F],
n: usize,
m: usize,
a: &mut [F],
difference: &mut [F],
) {
for i in 0..m {
let pole = conmat[i + n * m];
for j in 0..n {
difference[j] = conmat[i + j * m] - pole;
}
for (value, column) in
a[i * n..(i + 1) * n].iter_mut().zip(simi.chunks_exact(n))
{
*value = difference
.iter()
.zip(column)
.fold(F::zero(), |s, (&d, &v)| s + d * v);
}
}
}