pub fn fmingr(
n: usize,
p: &[f64],
ndeps: &[f64],
parscale: &[f64],
fnscale: f64,
bounds: Option<(Vec<f64>, Vec<f64>)>,
min_func: &dyn Fn(Vec<f64>) -> f64,
grad_func: Option<&dyn Fn(Vec<f64>) -> Vec<f64>>,
) -> (Vec<f64>, Vec<f64>) {
if let Some(gfunc) = grad_func {
let mut beta = vec![0.0; n];
for i in 0..n {
beta[i] = p[i] * parscale[i];
}
let s = gfunc(beta.clone());
let mut df = vec![0.0; n];
for i in 0..n {
df[i] = s[i] * parscale[i] / fnscale;
}
(beta, df)
} else {
let mut beta = vec![0.0; n];
let mut df = vec![0.0; n];
for i in 0..n {
beta[i] = p[i] * parscale[i];
}
for i in 0..n {
let mut bounded = false;
if let Some((upper, lower)) = &bounds {
if upper[i].is_finite() && lower[i].is_finite() {
let mut eps = ndeps[i];
let mut epsused = eps;
let mut tmp = p[i] + eps;
if tmp > upper[i] {
tmp = upper[i];
epsused = tmp - p[i];
}
beta[i] = tmp * parscale[i];
let s_1: f64 = min_func(beta.clone()) / fnscale;
tmp = p[i] - eps;
if tmp < lower[i] {
tmp = lower[i];
eps = p[i] - tmp;
}
beta[i] = tmp * parscale[i];
let s_2: f64 = min_func(beta.clone()) / fnscale;
df[i] = (s_1 - s_2) / (epsused - eps);
beta[i] = p[i] * parscale[i];
bounded = true;
}
}
if !bounded {
let mut eps = ndeps[i];
beta[i] = (p[i] + eps) * parscale[i];
let s_1: f64 = min_func(beta.clone()) / fnscale;
beta[i] = (p[i] - eps) * parscale[i];
let s_2: f64 = min_func(beta.clone()) / fnscale;
df[i] = (s_1 - s_2) / (2.0 * eps);
beta[i] = p[i] * parscale[i];
}
}
(beta, df)
}
}