use ffi;
use num::Float;
use libc::c_void;
pub struct MultiFitFunction<'r, T:'r> {
pub f: fn(x: &::VectorF64, params: &mut T, f: &::VectorF64) -> ::Value,
pub n: u64,
pub p: u64,
pub params: &'r mut T
}
pub struct MultiFitFdfSolver<'r, T:'r> {
_type: &'r MultiFitFdfSolverType<T>,
fdf: *mut c_void, pub x: ::VectorF64,
pub f: ::VectorF64,
pub j: ::MatrixF64,
pub dx: ::VectorF64,
state: LmderStateT
}
impl<'r, T> MultiFitFdfSolver<'r, T> {
pub fn new(_type: &'r MultiFitFdfSolverType<T>, n: u64, p: u64) -> Option<MultiFitFdfSolver<'r, T>> {
let mut r = MultiFitFdfSolver {
_type: _type,
fdf: ::std::ptr::null_mut(),
x: ::VectorF64::new(p).unwrap(),
f: ::VectorF64::new(n).unwrap(),
j: ::MatrixF64::new(n, p).unwrap(),
dx: ::VectorF64::new(p).unwrap(),
state: LmderStateT::new(n, p)
};
if ((*_type).alloc)(&mut r.state, n, p) == ::Value::Success {
Some(r)
} else {
None
}
}
pub fn set(&mut self, f: &mut MultiFitFunctionFdf<'r, T>, x: &::VectorF64) -> ::Value {
if self.f.len() != f.n {
rgsl_error!("function size does not match solver", ::Value::BadLen);
return ::Value::BadLen;
}
if self.x.len() != x.len() {
rgsl_error!("vector length does not match solver", ::Value::BadLen);
return ::Value::BadLen;
}
self.fdf = unsafe { ::std::mem::transmute(f) };
self.x.copy_from(x);
unsafe {
(self._type.set)(&mut self.state, ::std::mem::transmute(self.fdf), &mut self.x, &mut self.f, &mut self.j, &mut self.dx)
}
}
pub fn name(&self) -> &'static str {
self._type.name
}
pub fn iterate(&mut self) -> ::Value {
unsafe {
(self._type.iterate)(&mut self.state, ::std::mem::transmute(self.fdf), &mut self.x, &mut self.f, &mut self.j, &mut self.dx)
}
}
pub fn position(&'r self) -> &'r ::VectorF64 {
&self.x
}
#[allow(unused_assignments)]
pub fn driver(&mut self, max_iter: u64, epsabs: f64, epsrel: f64) -> ::Value {
let mut status = ::Value::Success;
let mut iter = 0u64;
loop {
status = self.iterate();
if status != ::Value::Success {
break;
}
status = gsl_multifit_test_delta(&self.dx, &self.x, epsabs, epsrel);
iter += 1;
if status != ::Value::Continue || iter >= max_iter {
break;
}
}
status
}
}
impl<'r, T> Drop for MultiFitFdfSolver<'r, T> {
fn drop(&mut self) {
}
}
#[allow(dead_code)]
pub struct MultiFitFdfSolverType<T> {
name: &'static str,
alloc: fn(state: &mut LmderStateT, n: u64, p: u64) -> ::Value,
set: fn(state: &mut LmderStateT, fdf: &mut MultiFitFunctionFdf<T>, x: &mut ::VectorF64, f: &mut ::VectorF64, j: &mut ::MatrixF64,
dx: &mut ::VectorF64) -> ::Value,
iterate: fn(state: &mut LmderStateT, fdf: &mut MultiFitFunctionFdf<T>, x: &mut ::VectorF64, f: &mut ::VectorF64,
j: &mut ::MatrixF64, dx: &mut ::VectorF64) -> ::Value,
free: fn(state: &mut LmderStateT)
}
impl<T> MultiFitFdfSolverType<T> {
pub fn lmder() -> MultiFitFdfSolverType<T> {
MultiFitFdfSolverType {
name: "lmder",
alloc: lmder_alloc,
set: lmder_set,
iterate: lmder_iterate,
free: lmder_free
}
}
pub fn lmsder() -> MultiFitFdfSolverType<T> {
MultiFitFdfSolverType {
name: "lmsder",
alloc: lmder_alloc,
set: lmsder_set,
iterate: lmder_iterate,
free: lmder_free
}
}
}
pub struct MultiFitFunctionFdf<'r, T:'r> {
pub f: fn(x: &::VectorF64, params: &mut T, f: &mut ::VectorF64) -> ::Value,
pub df: Option<fn(x: &::VectorF64, params: &mut T, df: &mut ::MatrixF64) -> ::Value>,
pub fdf: Option<fn(x: &::VectorF64, params: &mut T, f: &mut ::VectorF64, df: &mut ::MatrixF64) -> ::Value>,
pub n: u64,
pub p: u64,
pub params: &'r mut T
}
struct LmderStateT {
iter: u64,
xnorm: f64,
fnorm: f64,
delta: f64,
par: f64,
r: ::MatrixF64,
tau: ::VectorF64,
diag: ::VectorF64,
qtf: ::VectorF64,
newton: ::VectorF64,
gradient: ::VectorF64,
x_trial: ::VectorF64,
f_trial: ::VectorF64,
df: ::VectorF64,
sdiag: ::VectorF64,
rptdx: ::VectorF64,
w: ::VectorF64,
work1: ::VectorF64,
perm: ::Permutation
}
impl LmderStateT {
fn new(n: u64, p: u64) -> LmderStateT {
LmderStateT {
iter: 0u64,
xnorm: 0f64,
fnorm: 0f64,
delta: 0f64,
par: 0f64,
r: ::MatrixF64::new(n, p).unwrap(),
tau: ::VectorF64::new(if p < n {p} else {n}).unwrap(),
diag: ::VectorF64::new(p).unwrap(),
qtf: ::VectorF64::new(n).unwrap(),
newton: ::VectorF64::new(p).unwrap(),
gradient: ::VectorF64::new(p).unwrap(),
x_trial: ::VectorF64::new(p).unwrap(),
f_trial: ::VectorF64::new(n).unwrap(),
df: ::VectorF64::new(n).unwrap(),
sdiag: ::VectorF64::new(p).unwrap(),
rptdx: ::VectorF64::new(n).unwrap(),
w: ::VectorF64::new(n).unwrap(),
work1: ::VectorF64::new(p).unwrap(),
perm: ::Permutation::new(p).unwrap()
}
}
}
#[allow(unused_variables)]
fn lmder_alloc(state: &mut LmderStateT, n: u64, p: u64) -> ::Value {
::Value::Success
}
#[allow(unused_variables)]
fn lmder_free(state: &mut LmderStateT) {
}
fn lmder_set<T>(vstate: &mut LmderStateT, fdf: &mut MultiFitFunctionFdf<T>, x: &mut ::VectorF64, f: &mut ::VectorF64, J: &mut ::MatrixF64,
dx: &mut ::VectorF64) -> ::Value {
set(vstate, fdf, x, f, J, dx, 0)
}
fn lmsder_set<T>(vstate: &mut LmderStateT, fdf: &mut MultiFitFunctionFdf<T>, x: &mut ::VectorF64, f: &mut ::VectorF64, J: &mut ::MatrixF64,
dx: &mut ::VectorF64) -> ::Value {
set(vstate, fdf, x, f, J, dx, 1)
}
fn lmder_iterate<T>(vstate: &mut LmderStateT, fdf: &mut MultiFitFunctionFdf<T>, x: &mut ::VectorF64, f: &mut ::VectorF64, J: &mut ::MatrixF64,
dx: &mut ::VectorF64) -> ::Value {
iterate(vstate, fdf, x, f, J, dx, 0)
}
#[allow(dead_code)]
fn lmsder_iterate<T>(vstate: &mut LmderStateT, fdf: &mut MultiFitFunctionFdf<T>, x: &mut ::VectorF64, f: &mut ::VectorF64, J: &mut ::MatrixF64,
dx: &mut ::VectorF64) -> ::Value {
iterate(vstate, fdf, x, f, J, dx, 1)
}
fn compute_diag(J: &::MatrixF64, diag: &mut ::VectorF64) {
let n = J.size1();
let p = J.size2();
for j in 0..p {
let mut sum = 0f64;
for i in 0..n {
let jij = J.get(i, j);
sum += jij * jij;
}
if sum == 0f64 {
sum = 0f64;
}
diag.set(j, sum.sqrt());
}
}
fn update_diag(J: &::MatrixF64, diag: &mut ::VectorF64) {
let n = diag.len();
for j in 0..n {
let mut sum = 0f64;
for i in 0..n {
let jij = J.get(i, j);
sum += jij * jij;
}
if sum == 0f64 {
sum = 1f64;
}
let cnorm = sum.sqrt();
let diagj = diag.get(j);
if cnorm > diagj {
diag.set(j, cnorm);
}
}
}
fn scaled_enorm(d: &::VectorF64, f: &::VectorF64) -> f64 {
let mut e2 = 0f64;
let n = f.len();
for i in 0..n {
let fi = f.get(i);
let di = d.get(i);
let u = di * fi;
e2 += u * u;
}
e2.sqrt()
}
fn compute_delta(diag: &mut ::VectorF64, x: &mut ::VectorF64) -> f64 {
let Dx = scaled_enorm(diag, x);
let factor = 100f64;
if Dx > 0f64 {
factor * Dx
} else {
factor
}
}
fn set<T>(state: &mut LmderStateT, fdf: &mut MultiFitFunctionFdf<T>, x: &mut ::VectorF64, f: &mut ::VectorF64, j: &mut ::MatrixF64,
dx: &mut ::VectorF64, scale: i32) -> ::Value {
let mut signum = 0i32;
{
let status = match fdf.fdf {
Some(func) => {
func(x, fdf.params, f, j)
}
None => {
gsl_multifit_fdfsolver_dif_fdf(x, fdf, f, j)
}
};
if status != ::Value::Success {
return status;
}
}
state.par = 0f64;
state.iter = 1;
state.fnorm = enorm(f);
dx.set_all(0f64);
if scale != 0 {
compute_diag(j, &mut state.diag);
} else {
state.diag.set_all(1f64);
}
state.xnorm = scaled_enorm(&state.diag, x);
state.delta = compute_delta(&mut state.diag, x);
state.r.copy_from(j);
::linear_algebra::QRPT_decomp(&state.r, &state.tau, &state.perm, &mut signum, &state.work1);
state.rptdx.set_zero();
state.w.set_zero();
state.f_trial.set_zero();
::Value::Success
}
fn enorm(f: &::VectorF64) -> f64 {
::blas::level1::dnrm2(f)
}
fn compute_gradient_direction(r: &::MatrixF64, p: &::Permutation, qtf: &::VectorF64, diag: &::VectorF64, g: &mut ::VectorF64) {
let n = r.size2();
for j in 0..n {
let mut sum = 0f64;
for i in 0..(j + 1) {
sum += r.get(i, j) * qtf.get(i);
}
{
let pj = p.get(j);
let dpj = diag.get(pj);
g.set(j, sum / dpj);
}
}
}
fn compute_trial_step(x: &mut ::VectorF64, dx: &mut ::VectorF64, x_trial: &mut ::VectorF64) {
let n = x.len();
for i in 0..n {
let pi = dx.get(i);
let xi = x.get(i);
x_trial.set(i, xi + pi);
}
}
fn compute_actual_reduction(fnorm: f64, fnorm1: f64) -> f64 {
if 0.1f64 * fnorm1 < fnorm {
let u = fnorm1 / fnorm;
1f64 - u * u
} else {
-1f64
}
}
fn compute_rptdx(r: &::MatrixF64, p: &::Permutation, dx: &::VectorF64, rptdx: &mut ::VectorF64) {
let n = dx.len();
for i in 0..n {
let mut sum = 0f64;
for j in i..n {
let pj = p.get(j);
sum += r.get(i, j) * dx.get(pj);
}
rptdx.set(i, sum);
}
}
#[allow(unused_assignments)]
fn iterate<T>(state: &mut LmderStateT, fdf: &mut MultiFitFunctionFdf<T>, x: &mut ::VectorF64, f: &mut ::VectorF64, J: &mut ::MatrixF64,
dx: &mut ::VectorF64, scale: i32) -> ::Value {
let mut prered = 0f64;
let mut actred = 0f64;
let mut pnorm = 0f64;
let mut fnorm1 = 0f64;
let mut fnorm1p = 0f64;
let mut gnorm = 0f64;
let mut dirder = 0f64;
let mut iter = 0i32;
let p1 = 0.1f64;
let p25 = 0.25f64;
let p5 = 0.5f64;
let p75 = 0.75f64;
let p0001 = 0.0001f64;
if state.fnorm == 0f64 {
return ::Value::Success;
}
state.qtf.copy_from(f);
::linear_algebra::QR_QTvec(&state.r, &state.tau, &state.qtf);
compute_gradient_direction(&state.r, &state.perm, &state.qtf, &state.diag, &mut state.gradient);
{
let iamax = ::blas::level1::idamax(&state.gradient);
gnorm = unsafe { (state.gradient.get(iamax as u64) / state.fnorm).abs() };
}
loop {
iter += 1;
{
let status = lmpar(&mut state.r, &state.perm, &state.qtf, &state.diag, state.delta, &mut (state.par), &mut state.newton,
&mut state.gradient, &mut state.sdiag, dx, &mut state.w);
if status != ::Value::Success {
return status;
}
}
dx.scale(-1f64);
compute_trial_step(x, dx, &mut state.x_trial);
pnorm = scaled_enorm(&state.diag, dx);
if state.iter == 1 {
if pnorm < state.delta {
state.delta = pnorm;
}
}
{
let status = ((*fdf).f)(&state.x_trial, fdf.params, &mut state.f_trial);
if status != ::Value::Success {
return status;
}
}
fnorm1 = enorm(&state.f_trial);
actred = compute_actual_reduction(state.fnorm, fnorm1);
compute_rptdx(&state.r, &state.perm, dx, &mut state.rptdx);
fnorm1p = enorm(&state.rptdx);
{
let t1 = fnorm1p / state.fnorm;
let t2 = (state.par.sqrt() * pnorm) / state.fnorm;
prered = t1 * t1 + t2 * t2 / p5;
dirder = -(t1 * t1 + t2 * t2);
}
let ratio = if prered > 0f64 {
actred / prered
} else {
0f64
};
if ratio > p25 {
if state.par == 0f64 || ratio >= p75 {
state.delta = pnorm / p5;
state.par *= p5;
}
} else {
let mut temp = if actred >= 0f64 {p5} else {p5 * dirder / (dirder + p5 * actred)};
if p1 * fnorm1 >= state.fnorm || temp < p1 {
temp = p1;
}
state.delta = temp * state.delta.min(pnorm / p1);
state.par /= temp;
}
if ratio >= p0001 {
x.copy_from(&state.x_trial);
f.copy_from(&state.f_trial);
{
let status = match fdf.df {
Some(func) => {
func(&state.x_trial, fdf.params, J)
}
None => {
gsl_multifit_fdfsolver_dif_df(&mut state.x_trial, fdf, &mut state.f_trial, J)
}
};
if status != ::Value::Success {
return status;
}
}
state.xnorm = scaled_enorm(&state.diag, x);
state.fnorm = fnorm1;
state.iter += 1;
if scale != 0 {
update_diag(J, &mut state.diag);
}
{
let mut signum = 0;
state.r.copy_from(J);
::linear_algebra::QRPT_decomp(&state.r, &state.tau, &state.perm, &mut signum, &state.work1);
}
return ::Value::Success;
} else if actred.abs() <= ::DBL_EPSILON && prered <= ::DBL_EPSILON && p5 * ratio <= 1f64 {
return ::Value::TolF;
} else if state.delta <= ::DBL_EPSILON * state.xnorm {
return ::Value::TolX;
} else if gnorm <= ::DBL_EPSILON {
return ::Value::TolG;
} else if iter >= 10 {
break;
}
}
return ::Value::NoProg;
}
fn gsl_multifit_test_delta(dx: &::VectorF64, x: &::VectorF64, epsabs: f64, epsrel: f64) -> ::Value {
let mut ok = false;
if epsrel < 0f64 {
rgsl_error!("relative tolerance is negative", ::Value::BadTol);
return ::Value::BadTol;
}
for i in 0..x.len() {
let xi = x.get(i);
let dxi = dx.get(i);
let tolerance = epsabs + epsrel * xi.abs();
if dxi.abs() < tolerance {
ok = true;
} else {
ok = false;
break;
}
}
if ok {
::Value::Success
} else {
::Value::Continue
}
}
fn gsl_multifit_fdfsolver_dif_fdf<T>(x: &mut ::VectorF64, fdf: &mut MultiFitFunctionFdf<T>, f: &mut ::VectorF64,
j: &mut ::MatrixF64) -> ::Value {
let mut status = ((*fdf).f)(x, fdf.params, f); if status != ::Value::Success {
return status;
}
status = fdjac(x, fdf, f, j);
if status != ::Value::Success {
return status;
}
status
}
fn fdjac<T>(x: &mut ::VectorF64, fdf: &mut MultiFitFunctionFdf<T>, f: &::VectorF64, jm: &mut ::MatrixF64) -> ::Value {
let mut status = ::Value::Success;
let epsfcn = 0f64;
let eps = (epsfcn.max(::DBL_EPSILON)).sqrt();
for j in 0..fdf.p {
let xj = x.get(j);
let (mut v, _) = jm.get_col(j).unwrap();
let mut h = eps * xj.abs();
if h == 0f64 {
h = eps;
}
x.set(j, xj + h);
status = ((*fdf).f)(x, fdf.params, &mut v); if status != ::Value::Success {
return status;
}
x.set(j, xj);
h = 1f64 / h;
for i in 0..fdf.n {
let fnext = v.get(i);
let fi = f.get(i);
jm.set(i, j, (fnext - fi) * h);
}
}
status
}
fn gsl_multifit_fdfsolver_dif_df<T>(x: &mut ::VectorF64, fdf: &mut MultiFitFunctionFdf<T>, f: &::VectorF64,
J: &mut ::MatrixF64) -> ::Value {
fdjac(x, fdf, f, J)
}
#[allow(unused_assignments)]
fn lmpar(r: &mut ::MatrixF64, perm: &::Permutation, qtf: &::VectorF64, diag: &::VectorF64, delta: f64, par_inout: &mut f64,
newton: &mut ::VectorF64, gradient: &mut ::VectorF64, sdiag: &mut ::VectorF64, x: &mut ::VectorF64,
w: &mut ::VectorF64) -> ::Value {
let mut dxnorm = 0f64;
let mut gnorm = 0f64;
let mut fp = 0f64;
let mut fp_old = 0f64;
let mut par_lower = 0f64;
let mut par_upper = 0f64;
let mut par_c = 0f64;
let mut par = *par_inout;
let mut iter = 0u64;
compute_newton_direction(r, perm, qtf, newton);
dxnorm = scaled_enorm(diag, newton);
fp = dxnorm - delta;
if fp <= 0.1 * delta {
x.copy_from(newton);
*par_inout = 0f64;
return ::Value::Success;
}
compute_newton_bound(r, newton, dxnorm, perm, diag, w);
{
let wnorm = enorm(w);
let phider = wnorm * wnorm;
par_lower = if wnorm > 0f64 {
fp / (delta * phider)
} else {
0f64
};
}
compute_gradient_direction(r, perm, qtf, diag, gradient);
gnorm = enorm(gradient);
par_upper = gnorm / delta;
if par_upper == 0f64 {
par_upper = ::DBL_MIN / delta.min(0.1f64);
}
if par > par_upper {
par = par_upper;
} else if par < par_lower {
par = par_lower;
}
if par == 0f64 {
par = gnorm / dxnorm;
}
loop {
iter += 1;
if par < par_lower || par > par_upper {
par = (par_lower * par_upper).sqrt().max(0.001f64 * par_upper);
}
if par == 0f64 {
par = (0.001f64 * par_upper).max(::DBL_MIN);
}
{
let sqrt_par = par.sqrt();
qrsolv(r, perm, sqrt_par, diag, qtf, x, sdiag, w);
}
dxnorm = scaled_enorm(diag, x);
fp_old = fp;
fp = dxnorm - delta;
if fp.abs() <= 0.1f64 * delta {
break;
}
if par_lower == 0f64 && fp <= fp_old && fp_old < 0f64 {
break;
}
if iter == 10 {
break;
}
compute_newton_correction(r, sdiag, perm, x, dxnorm, diag, w);
{
let wnorm = enorm(w);
par_c = fp / (delta * wnorm * wnorm);
}
if fp > 0f64 {
if par > par_lower {
par_lower = par;
}
} else if fp < 0f64 {
if par < par_upper {
par_upper = par;
}
}
par = par_lower.max(par + par_c);
}
*par_inout = par;
::Value::Success
}
fn compute_newton_direction(r: &::MatrixF64, perm: &::Permutation, qtf: &::VectorF64, x: &mut ::VectorF64) {
let n = r.size2();
for i in 0..n {
let qtfi = qtf.get(i);
x.set(i, qtfi);
}
let nsing = count_nsing(r);
if nsing < n {
for i in nsing..n {
x.set(i, 0f64);
}
}
if nsing > 0u64 {
for j in nsing..0 {
let rjj = r.get(j, j);
let temp = x.get(j) / rjj;
x.set(j, temp);
for i in 0..j {
let rij = r.get(i, j);
let xi = x.get(i);
x.set(i, xi - rij * temp);
}
}
}
perm.permute_vector_inverse(x);
}
fn compute_newton_bound(r: &::MatrixF64, x: &::VectorF64, dxnorm: f64, perm: &::Permutation, diag: &::VectorF64,
w: &mut ::VectorF64) {
let n = r.size2();
let nsing = count_nsing(r);
if nsing < n {
w.set_zero();
return;
}
for i in 0..n {
let pi = perm.get(i);
let dpi = diag.get(pi);
let xpi = x.get(pi);
w.set(i, dpi * (dpi * xpi / dxnorm));
}
for j in 0..n {
let mut sum = 0f64;
for i in 0..j {
sum += r.get(i, j) * w.get(i);
}
{
let rjj = r.get(j, j);
let wj = w.get(j);
w.set(j, (wj - sum) / rjj);
}
}
}
fn qrsolv(r: &mut ::MatrixF64, p: &::Permutation, lambda: f64, diag: &::VectorF64, qtb: &::VectorF64,
x: &mut ::VectorF64, sdiag: &mut ::VectorF64, wa: &mut ::VectorF64) -> ::Value {
let n = r.size2();
let mut j = 0;
while j < n {
let rjj = r.get(j, j);
let qtbj = qtb.get(j);
let mut i = j + 1;
while i < n {
let rji = r.get(j, i);
r.set(i, j, rji);
i += 1;
}
x.set(j, rjj);
wa.set(j, qtbj);
j += 1;
}
j = 0;
while j < n {
let pj = p.get(j);
let diagpj = lambda * diag.get(pj);
if diagpj == 0f64 {
continue;
}
sdiag.set(j, diagpj);
let mut k = j + 1;
while k < n {
sdiag.set(k, 0f64);
k += 1;
}
let mut qtbpj = 0f64;
k = j;
while k < n {
let wak = wa.get(k);
let rkk = r.get(k, k);
let sdiagk = sdiag.get(k);
if sdiagk == 0f64 {
continue;
}
let (sine, cosine) = if rkk.abs() < sdiagk.abs() {
let cotangent = rkk / sdiagk;
let t_sine = 0.5f64 / (0.25f64 + 0.25f64 * cotangent * cotangent).sqrt();
(t_sine, t_sine * cotangent)
} else {
let tangent = sdiagk / rkk;
let t_cos = 0.5f64 / (0.25f64 + 0.25f64 * tangent * tangent).sqrt();
(t_cos * tangent, t_cos)
};
{
let new_rkk = cosine * rkk + sine * sdiagk;
let new_wak = cosine * wak + sine * qtbpj;
qtbpj = -sine * wak + cosine * qtbpj;
r.set(k, k, new_rkk);
wa.set(k, new_wak);
}
let mut i = k + 1;
while i < n {
let rik = r.get(i, k);
let sdiagi = sdiag.get(i);
let new_rik = cosine * rik + sine * sdiagi;
let new_sdiagi = -sine * rik + cosine * sdiagi;
r.set(i, k, new_rik);
sdiag.set(i, new_sdiagi);
i += 1;
}
k += 1;
}
{
let rjj = r.get(j, j);
let xj = x.get(j);
sdiag.set(j, rjj);
r.set(j, j, xj);
}
j += 1;
}
let mut nsing = n;
j = 0;
while j < n {
let sdiagj = sdiag.get(j);
if sdiagj == 0f64 {
nsing = j;
break;
}
j += 1;
}
j = nsing;
while j < n {
wa.set(j, 0f64);
j += 1;
}
let mut k = 0;
while k < nsing {
let mut sum = 0f64;
j = (nsing - 1) - k;
let mut i = j + 1;
while i < nsing {
sum += r.get(i, j) * wa.get(i);
i += 1;
}
{
let waj = wa.get(j);
let sdiagj = sdiag.get(j);
wa.set(j, (waj - sum) / sdiagj);
}
k += 1;
}
j = 0;
while j < n {
let pj = p.get(j);
let waj = wa.get(j);
x.set(pj, waj);
j += 1;
}
::Value::Success
}
fn compute_newton_correction(r: &::MatrixF64, sdiag: &::VectorF64, p: &::Permutation, x: &mut ::VectorF64, dxnorm: f64,
diag: &::VectorF64, w: &mut ::VectorF64) {
let n = r.size2();
let mut i = 0;
while i < n {
let pi = p.get(i);
let dpi = diag.get(pi);
let xpi = x.get(pi);
w.set(i, dpi * (dpi * xpi) / dxnorm);
i += 1;
}
let mut j = 0;
while j < n {
let sj = sdiag.get(j);
let wj = w.get(j);
let tj = wj / sj;
w.set(j, tj);
let mut i = j + 1;
while i < n {
let rij = r.get (i, j);
let wi = w.get (i);
w.set (i, wi - rij * tj);
i += 1;
}
j += 1;
}
}
fn count_nsing(r: &::MatrixF64) -> u64 {
let n = r.size2();
let mut i = 0u64;
while i < n {
let rii = r.get(i, i);
if rii == 0f64 {
break;
}
i += 1;
}
i
}