1use nalgebra as na;
2use std::ops::Mul;
4
5pub(crate) struct Corrector {
6 sqrt_rho1: f64,
7 residual_scaling: f64,
8 alpha_sq_norm: f64,
9}
10
11impl Corrector {
12 pub fn new(sq_norm: f64, rho: &[f64; 3]) -> Corrector {
13 let sqrt_rho1 = rho[1].sqrt();
14 if (sq_norm == 0.0) || (rho[2] <= 0.0) {
16 let residual_scaling = sqrt_rho1;
17 let alpha_sq_norm = 0.0;
18 Corrector {
19 sqrt_rho1,
20 residual_scaling,
21 alpha_sq_norm,
22 }
23 } else {
24 let d = 1.0 + 2.0 * sq_norm * rho[2] / rho[1];
25
26 let alpha = 1.0 - d.sqrt();
27
28 let residual_scaling = sqrt_rho1 / (1.0 - alpha);
29 let alpha_sq_norm = alpha / sq_norm;
30 Corrector {
31 sqrt_rho1,
32 residual_scaling,
33 alpha_sq_norm,
34 }
35 }
36 }
37 pub fn correct_jacobian(&self, residuals: &na::DVector<f64>, jacobian: &mut na::DMatrix<f64>) {
38 if self.alpha_sq_norm == 0.0 {
40 *jacobian = jacobian.clone().mul(self.sqrt_rho1);
41 return;
42 }
43
44 let r_rtj = residuals.clone() * residuals.transpose() * jacobian.clone();
46 *jacobian = (jacobian.clone() - r_rtj.mul(self.alpha_sq_norm)).mul(self.sqrt_rho1);
47 }
48 pub fn correct_residuals(&self, residuals: &mut na::DVector<f64>) {
49 *residuals = residuals.clone().mul(self.residual_scaling);
50 }
51}