fn iterate(&mut self, iter_ix: usize) -> f64 {
        let mut th_ix = 0;
        let mut abs_err = 0.0;
        for i in 1..self.elements.len() {
            if self.elements[i].is_auto_p1()
                && self.prev_el(i).map(Element::is_auto_p2).unwrap_or(false)
            {
                let prev_seg = &self.segments[self.prev_ix(i) - 1];
                let prev_ch = prev_seg.chord().hypot();
                let seg = &self.segments[i - 1];
                let this_ch = seg.chord().hypot();
                let k_prev = prev_seg.k1;
                let k_this = seg.k0;
                let k_scale = (prev_ch * this_ch).sqrt();
                let k_err = (k_prev * k_scale).atan() - (k_this * k_scale).atan();
                abs_err += k_err.abs();

                // Compute error derivative by differencing. A more sophisticated approach
                // would be analytical derivatives.
                const EPSILON: f64 = 1e-3;
                let th1p = prev_seg.th1 + EPSILON;
                let params0 = ThetaParams {
                    th0: -prev_seg.th0,
                    bias0: prev_seg.hb.bias0,
                    th1: -th1p,
                    bias1: simple_spline::bias_for_theta(th1p),
                };
                let seg0p = HyperBezier::solve_for_theta(&params0);
                let k0p = seg0p.compute().k1 / prev_ch;

                let th0p = seg.th0 - EPSILON;
                let params1 = ThetaParams {
                    th0: -th0p,
                    bias0: simple_spline::bias_for_theta(th0p),
                    th1: -seg.th1,
                    bias1: seg.hb.bias1,
                };
                let seg1p = HyperBezier::solve_for_theta(&params1);
                let k1p = seg1p.compute().k0 / this_ch;

                let k_errp = (k0p * k_scale).atan() - (k1p * k_scale).atan();
                let derr = (k_errp - k_err) * (1.0 / EPSILON);
                //eprintln!("{}: err = {:.3}, derr = {:.3}", i, k_err, derr);
                self.dths[th_ix] = k_err / derr;
                th_ix += 1;
            }
        }
        let scale = (0.25 * (iter_ix as f64 + 1.0)).tanh();
        for (th, dth) in self.ths.iter_mut().zip(&self.dths) {
            *th += scale * dth;
        }
        abs_err
    }
/// Iterate towards reducing error metric.
///
/// Returns the absolute error (after arctan linearization).
Iterate towards reducing error metric.
Returns the absolute error (after arctan linearization).
Iterate towards reducing error metric . Returns the absolute error ( after arctan linearization ) .
fn iterate(&mut self, iter_ix: usize) -> f64 {
        let mut th_ix = 0;
        let mut abs_err = 0.0;
        for i in 1..self.elements.len() {
            if self.elements[i].is_auto_p1()
                && self.prev_el(i).map(Element::is_auto_p2).unwrap_or(false)
            {
                let prev_seg = &self.segments[self.prev_ix(i) - 1];
                let prev_ch = prev_seg.chord().hypot();
                let seg = &self.segments[i - 1];
                let this_ch = seg.chord().hypot();
                let k_prev = prev_seg.k1;
                let k_this = seg.k0;
                let k_scale = (prev_ch * this_ch).sqrt();
                let k_err = (k_prev * k_scale).atan() - (k_this * k_scale).atan();
                abs_err += k_err.abs();
                // Compute error derivative by differencing. A more sophisticated approach
                // would be analytical derivatives.
                const EPSILON: f64 = 1e-3;
                let th1p = prev_seg.th1 + EPSILON;
                let params0 = ThetaParams {
                    th0: -prev_seg.th0,
                    bias0: prev_seg.hb.bias0,
                    th1: -th1p,
                    bias1: simple_spline::bias_for_theta(th1p),
                };
                let seg0p = HyperBezier::solve_for_theta(&params0);
                let k0p = seg0p.compute().k1 / prev_ch;
                let th0p = seg.th0 - EPSILON;
                let params1 = ThetaParams {
                    th0: -th0p,
                    bias0: simple_spline::bias_for_theta(th0p),
                    th1: -seg.th1,
                    bias1: seg.hb.bias1,
                };
                let seg1p = HyperBezier::solve_for_theta(&params1);
                let k1p = seg1p.compute().k0 / this_ch;
                let k_errp = (k0p * k_scale).atan() - (k1p * k_scale).atan();
                let derr = (k_errp - k_err) * (1.0 / EPSILON);
                //eprintln!("{}: err = {:.3}, derr = {:.3}", i, k_err, derr);
                self.dths[th_ix] = k_err / derr;
                th_ix += 1;
            }
        }
        let scale = (0.25 * (iter_ix as f64 + 1.0)).tanh();
        for (th, dth) in self.ths.iter_mut().zip(&self.dths) {
            *th += scale * dth;
        }
        abs_err
    }
fn iterate ( & mut self , iter_ix : usize ) -> f64 { let mut th_ix = 0 ; let mut abs_err = 0.0 ; for i in 1 .. self . elements . len ( ) { if self . elements [ i ] . is_auto_p1 ( ) && self . prev_el ( i ) . map ( Element :: is_auto_p2 ) . unwrap_or ( false ) { let prev_seg = & self . segments [ self . prev_ix ( i ) - 1 ] ; let prev_ch = prev_seg . chord ( ) . hypot ( ) ; let seg = & self . segments [ i - 1 ] ; let this_ch = seg . chord ( ) . hypot ( ) ; let k_prev = prev_seg . k1 ; let k_this = seg . k0 ; let k_scale = ( prev_ch * this_ch ) . sqrt ( ) ; let k_err = ( k_prev * k_scale ) . atan ( ) - ( k_this * k_scale ) . atan ( ) ; abs_err += k_err . abs ( ) ; // Compute error derivative by differencing. A more sophisticated approach // would be analytical derivatives. const EPSILON : f64 = 1e-3 ; let th1p = prev_seg . th1 + EPSILON ; let params0 = ThetaParams { th0 : - prev_seg . th0 , bias0 : prev_seg . hb . bias0 , th1 : - th1p , bias1 : simple_spline :: bias_for_theta ( th1p ) , } ; let seg0p = HyperBezier :: solve_for_theta ( & params0 ) ; let k0p = seg0p . compute ( ) . k1 / prev_ch ; let th0p = seg . th0 - EPSILON ; let params1 = ThetaParams { th0 : - th0p , bias0 : simple_spline :: bias_for_theta ( th0p ) , th1 : - seg . th1 , bias1 : seg . hb . bias1 , } ; let seg1p = HyperBezier :: solve_for_theta ( & params1 ) ; let k1p = seg1p . compute ( ) . k0 / this_ch ; let k_errp = ( k0p * k_scale ) . atan ( ) - ( k1p * k_scale ) . atan ( ) ; let derr = ( k_errp - k_err ) * ( 1.0 / EPSILON ) ; //eprintln!("{}: err = {:.3}, derr = {:.3}", i, k_err, derr); self . dths [ th_ix ] = k_err / derr ; th_ix += 1 ; } } let scale = ( 0.25 * ( iter_ix as f64 + 1.0 ) ) . tanh ( ) ; for ( th , dth ) in self . ths . iter_mut ( ) . zip ( & self . dths ) { * th += scale * dth ; } abs_err }
Iterate towards reducing error metric.
Iterate towards reducing error metric .
&mut self
iter_ix
usize
&mut self
iter_ix
usize