fn middle_snake<T: Eq>(
        old: &[T],
        old_range: Range<usize>,
        new: &[T],
        new_range: Range<usize>,
        frontiers: &mut MyersFrontiers,
    ) -> Coordinates<usize> {
        let n = old_range.len() as i32;
        let m = new_range.len() as i32;
        let delta = n - m;
        let is_odd = delta % 2 == 1;
        let midpoint = ((m + n) as f32 / 2.00).ceil() as i32 + 1;

        let fwd_front = &mut frontiers.forward;
        let rev_front = &mut frontiers.reverse;

        fwd_front[1] = 0;
        rev_front[1] = 0;

        for d in 0..=midpoint {
            // Find the end of the furthest reaching forward d-path
            for k in (-d..=d).rev().step_by(2) {
                // k == -d and k != d are just bounds checks to make sure we don't try to compare
                // values outside of the [-d, d] range. We check for the furthest reaching forward
                // frontier by seeing which diagonal has the highest x value.
                let mut x = if k == -d || (k != d && fwd_front[k + 1] >= fwd_front[k - 1]) {
                    // If the longest diagonal is from the vertically connected d - 1 path. The y
                    // component is implicitly added when we compute y below with a different k value.
                    fwd_front[k + 1]
                } else {
                    // If the longest diagonal is from the horizontally connected d - 1 path. We
                    // add one here for the horizontal connection (x, y) -> (x + 1, y).
                    fwd_front[k - 1] + 1
                };
                let y = x - k;

                // Coordinates of the first point in the snake
                let (x0, y0) = (x, y);

                // Extend the snake
                if x < n && y < m {
                    debug_assert!(x >= 0);
                    debug_assert!(y >= 0);

                    let common_pref_len = common_prefix_len(
                        old,
                        old_range.start + (x as usize)..old_range.end,
                        new,
                        new_range.start + (y as usize)..new_range.end,
                    );
                    x += common_pref_len as i32;
                }

                fwd_front[k] = x;

                // If delta is odd and k is in the defined range
                if is_odd && (k - delta).abs() < d {
                    // If the path overlaps the furthest reaching reverse d - 1 path in diagonal k
                    // then the length of an SES is 2D - 1, and the last snake of the forward path
                    // is the middle snake.
                    let reverse_x = rev_front[-(k - delta)];

                    // We convert everything over to signed integers first so we can check for any
                    // overflow errors.
                    let old = (old_range.start as i32) + x0;
                    let new = (new_range.start as i32) + y0;

                    debug_assert!(
                        old >= (old_range.start as i32) && old <= (old_range.end as i32),
                        "expected old={} in {}..{}",
                        old,
                        old_range.start,
                        old_range.end,
                    );
                    debug_assert!(
                        new >= (new_range.start as i32) && new <= (new_range.end as i32),
                        "expected new={} in {}..{}",
                        new,
                        new_range.start,
                        new_range.end,
                    );

                    // NOTE: that we can convert x and y to `usize` because they are both within
                    // the range of the length of the inputs, which are valid usize values. This property
                    // is also checked with assertions in debug releases.
                    if x + reverse_x >= n {
                        return Coordinates {
                            old: old as usize,
                            new: new as usize,
                        };
                    }
                }
            }

            // Find the end of the furthest reaching reverse d-path
            for k in (-d..=d).rev().step_by(2) {
                // k == d and k != -d are just bounds checks to make sure we don't try to compare
                // anything out of range, as explained above. In the reverse path we check to see
                // which diagonal has the smallest *real* x value because we're trying to go from
                // the bottom-right to the top-left of the matrix. Note that we're looking for the
                // biggest x value in the reverse frontier, which will be subtracted from the total
                // length.
                let mut x = if k == -d || (k != d && rev_front[k + 1] >= rev_front[k - 1]) {
                    // If the longest diagonal is from the horizontally connected d - 1 path.
                    rev_front[k + 1]
                } else {
                    // If the longest diagonal is from the vertically connected d - 1 path. The y
                    // value is implicitly handled when we compute y with a different k value.
                    rev_front[k - 1] + 1
                };
                let mut y = x - k;

                // Advance the diagonal as far as possible
                if x < n && y < m {
                    debug_assert!(x >= 0);
                    debug_assert!(y >= 0);
                    debug_assert!(n - x >= 0);
                    debug_assert!(m - y >= 0);

                    let common_suf_len = common_suffix_len(
                        old,
                        old_range.start..old_range.start + (n as usize) - (x as usize),
                        new,
                        new_range.start..new_range.start + (m as usize) - (y as usize),
                    );
                    x += common_suf_len as i32;
                    y += common_suf_len as i32;
                }
                rev_front[k] = x;

                // If delta is even and k is in the defined range, check for an overlap
                if !is_odd && (k - delta).abs() <= d {
                    let forward_x = fwd_front[-(k - delta)];

                    // If forward_x + reverse_x >= n, the forward and backward paths make up a full
                    // path, so we have a possible overlap. So return the furthest reaching reverse
                    // path as the middle snake.
                    // NOTE: that we can convert x and y to `usize` because they are both within
                    // the range of the length of the inputs, which are valid usize values.
                    if forward_x + x >= n {
                        let old = n - x + (old_range.start as i32);
                        let new = m - y + (new_range.start as i32);

                        debug_assert!(
                            old >= (old_range.start as i32) && old <= (old_range.end as i32),
                            "expected old={} in {}..{}",
                            old,
                            old_range.start,
                            old_range.end,
                        );
                        debug_assert!(
                            new >= (new_range.start as i32) && new <= (new_range.end as i32),
                            "expected new={} in {}..{}",
                            new,
                            new_range.start,
                            new_range.end,
                        );

                        return Coordinates {
                            old: old as usize,
                            new: new as usize,
                        };
                    }
                }
            }
        }
        unreachable!();
    }
/// Calculate the (x, y) coordinates of the midpoint of the optimal path.
///
/// This implementation directly derives from "An O(ND) Difference Algorithm and Its Variations"
/// by Myers. This will compute the location of the middle snake and the length of the optimal
/// shortest edit script.
Calculate the (x, y) coordinates of the midpoint of the optimal path.
This implementation directly derives from "An O(ND) Difference Algorithm and Its Variations"
by Myers. This will compute the location of the middle snake and the length of the optimal
shortest edit script.
Calculate the ( x y ) coordinates of the midpoint of the optimal path . This implementation directly derives from " An O ( ND ) Difference Algorithm and Its Variations " by Myers . This will compute the location of the middle snake and the length of the optimal shortest edit script .
fn middle_snake<T: Eq>(
        old: &[T],
        old_range: Range<usize>,
        new: &[T],
        new_range: Range<usize>,
        frontiers: &mut MyersFrontiers,
    ) -> Coordinates<usize> {
        let n = old_range.len() as i32;
        let m = new_range.len() as i32;
        let delta = n - m;
        let is_odd = delta % 2 == 1;
        let midpoint = ((m + n) as f32 / 2.00).ceil() as i32 + 1;
        let fwd_front = &mut frontiers.forward;
        let rev_front = &mut frontiers.reverse;
        fwd_front[1] = 0;
        rev_front[1] = 0;
        for d in 0..=midpoint {
            // Find the end of the furthest reaching forward d-path
            for k in (-d..=d).rev().step_by(2) {
                // k == -d and k != d are just bounds checks to make sure we don't try to compare
                // values outside of the [-d, d] range. We check for the furthest reaching forward
                // frontier by seeing which diagonal has the highest x value.
                let mut x = if k == -d || (k != d && fwd_front[k + 1] >= fwd_front[k - 1]) {
                    // If the longest diagonal is from the vertically connected d - 1 path. The y
                    // component is implicitly added when we compute y below with a different k value.
                    fwd_front[k + 1]
                } else {
                    // If the longest diagonal is from the horizontally connected d - 1 path. We
                    // add one here for the horizontal connection (x, y) -> (x + 1, y).
                    fwd_front[k - 1] + 1
                };
                let y = x - k;
                // Coordinates of the first point in the snake
                let (x0, y0) = (x, y);
                // Extend the snake
                if x < n && y < m {
                    debug_assert!(x >= 0);
                    debug_assert!(y >= 0);
                    let common_pref_len = common_prefix_len(
                        old,
                        old_range.start + (x as usize)..old_range.end,
                        new,
                        new_range.start + (y as usize)..new_range.end,
                    );
                    x += common_pref_len as i32;
                }
                fwd_front[k] = x;
                // If delta is odd and k is in the defined range
                if is_odd && (k - delta).abs() < d {
                    // If the path overlaps the furthest reaching reverse d - 1 path in diagonal k
                    // then the length of an SES is 2D - 1, and the last snake of the forward path
                    // is the middle snake.
                    let reverse_x = rev_front[-(k - delta)];
                    // We convert everything over to signed integers first so we can check for any
                    // overflow errors.
                    let old = (old_range.start as i32) + x0;
                    let new = (new_range.start as i32) + y0;
                    debug_assert!(
                        old >= (old_range.start as i32) && old <= (old_range.end as i32),
                        "expected old={} in {}..{}",
                        old,
                        old_range.start,
                        old_range.end,
                    );
                    debug_assert!(
                        new >= (new_range.start as i32) && new <= (new_range.end as i32),
                        "expected new={} in {}..{}",
                        new,
                        new_range.start,
                        new_range.end,
                    );
                    // NOTE: that we can convert x and y to `usize` because they are both within
                    // the range of the length of the inputs, which are valid usize values. This property
                    // is also checked with assertions in debug releases.
                    if x + reverse_x >= n {
                        return Coordinates {
                            old: old as usize,
                            new: new as usize,
                        };
                    }
                }
            }
            // Find the end of the furthest reaching reverse d-path
            for k in (-d..=d).rev().step_by(2) {
                // k == d and k != -d are just bounds checks to make sure we don't try to compare
                // anything out of range, as explained above. In the reverse path we check to see
                // which diagonal has the smallest *real* x value because we're trying to go from
                // the bottom-right to the top-left of the matrix. Note that we're looking for the
                // biggest x value in the reverse frontier, which will be subtracted from the total
                // length.
                let mut x = if k == -d || (k != d && rev_front[k + 1] >= rev_front[k - 1]) {
                    // If the longest diagonal is from the horizontally connected d - 1 path.
                    rev_front[k + 1]
                } else {
                    // If the longest diagonal is from the vertically connected d - 1 path. The y
                    // value is implicitly handled when we compute y with a different k value.
                    rev_front[k - 1] + 1
                };
                let mut y = x - k;
                // Advance the diagonal as far as possible
                if x < n && y < m {
                    debug_assert!(x >= 0);
                    debug_assert!(y >= 0);
                    debug_assert!(n - x >= 0);
                    debug_assert!(m - y >= 0);
                    let common_suf_len = common_suffix_len(
                        old,
                        old_range.start..old_range.start + (n as usize) - (x as usize),
                        new,
                        new_range.start..new_range.start + (m as usize) - (y as usize),
                    );
                    x += common_suf_len as i32;
                    y += common_suf_len as i32;
                }
                rev_front[k] = x;
                // If delta is even and k is in the defined range, check for an overlap
                if !is_odd && (k - delta).abs() <= d {
                    let forward_x = fwd_front[-(k - delta)];
                    // If forward_x + reverse_x >= n, the forward and backward paths make up a full
                    // path, so we have a possible overlap. So return the furthest reaching reverse
                    // path as the middle snake.
                    // NOTE: that we can convert x and y to `usize` because they are both within
                    // the range of the length of the inputs, which are valid usize values.
                    if forward_x + x >= n {
                        let old = n - x + (old_range.start as i32);
                        let new = m - y + (new_range.start as i32);
                        debug_assert!(
                            old >= (old_range.start as i32) && old <= (old_range.end as i32),
                            "expected old={} in {}..{}",
                            old,
                            old_range.start,
                            old_range.end,
                        );
                        debug_assert!(
                            new >= (new_range.start as i32) && new <= (new_range.end as i32),
                            "expected new={} in {}..{}",
                            new,
                            new_range.start,
                            new_range.end,
                        );
                        return Coordinates {
                            old: old as usize,
                            new: new as usize,
                        };
                    }
                }
            }
        }
        unreachable!();
    }
fn middle_snake < T : Eq > ( old : & [ T ] , old_range : Range < usize > , new : & [ T ] , new_range : Range < usize > , frontiers : & mut MyersFrontiers , ) -> Coordinates < usize > { let n = old_range . len ( ) as i32 ; let m = new_range . len ( ) as i32 ; let delta = n - m ; let is_odd = delta % 2 == 1 ; let midpoint = ( ( m + n ) as f32 / 2.00 ) . ceil ( ) as i32 + 1 ; let fwd_front = & mut frontiers . forward ; let rev_front = & mut frontiers . reverse ; fwd_front [ 1 ] = 0 ; rev_front [ 1 ] = 0 ; for d in 0 ..= midpoint { // Find the end of the furthest reaching forward d-path for k in ( - d ..= d ) . rev ( ) . step_by ( 2 ) { // k == -d and k != d are just bounds checks to make sure we don't try to compare // values outside of the [-d, d] range. We check for the furthest reaching forward // frontier by seeing which diagonal has the highest x value. let mut x = if k == - d || ( k != d && fwd_front [ k + 1 ] >= fwd_front [ k - 1 ] ) { // If the longest diagonal is from the vertically connected d - 1 path. The y // component is implicitly added when we compute y below with a different k value. fwd_front [ k + 1 ] } else { // If the longest diagonal is from the horizontally connected d - 1 path. We // add one here for the horizontal connection (x, y) -> (x + 1, y). fwd_front [ k - 1 ] + 1 } ; let y = x - k ; // Coordinates of the first point in the snake let ( x0 , y0 ) = ( x , y ) ; // Extend the snake if x < n && y < m { debug_assert ! ( x 0 ) ; debug_assert ! ( y 0 ) ; let common_pref_len = common_prefix_len ( old , old_range . start + ( x as usize ) .. old_range . end , new , new_range . start + ( y as usize ) .. new_range . end , ) ; x += common_pref_len as i32 ; } fwd_front [ k ] = x ; // If delta is odd and k is in the defined range if is_odd && ( k - delta ) . abs ( ) < d { // If the path overlaps the furthest reaching reverse d - 1 path in diagonal k // then the length of an SES is 2D - 1, and the last snake of the forward path // is the middle snake. let reverse_x = rev_front [ - ( k - delta ) ] ; // We convert everything over to signed integers first so we can check for any // overflow errors. let old = ( old_range . start as i32 ) + x0 ; let new = ( new_range . start as i32 ) + y0 ; debug_assert ! ( old ( old_range start as i32 ) old ( old_range end as i32 ) " " old old_range start old_range end ) ; debug_assert ! ( new ( new_range start as i32 ) new ( new_range end as i32 ) " " new new_range start new_range end ) ; // NOTE: that we can convert x and y to `usize` because they are both within // the range of the length of the inputs, which are valid usize values. This property // is also checked with assertions in debug releases. if x + reverse_x >= n { return Coordinates { old : old as usize , new : new as usize , } ; } } } // Find the end of the furthest reaching reverse d-path for k in ( - d ..= d ) . rev ( ) . step_by ( 2 ) { // k == d and k != -d are just bounds checks to make sure we don't try to compare // anything out of range, as explained above. In the reverse path we check to see // which diagonal has the smallest *real* x value because we're trying to go from // the bottom-right to the top-left of the matrix. Note that we're looking for the // biggest x value in the reverse frontier, which will be subtracted from the total // length. let mut x = if k == - d || ( k != d && rev_front [ k + 1 ] >= rev_front [ k - 1 ] ) { // If the longest diagonal is from the horizontally connected d - 1 path. rev_front [ k + 1 ] } else { // If the longest diagonal is from the vertically connected d - 1 path. The y // value is implicitly handled when we compute y with a different k value. rev_front [ k - 1 ] + 1 } ; let mut y = x - k ; // Advance the diagonal as far as possible if x < n && y < m { debug_assert ! ( x 0 ) ; debug_assert ! ( y 0 ) ; debug_assert ! ( n x 0 ) ; debug_assert ! ( m y 0 ) ; let common_suf_len = common_suffix_len ( old , old_range . start .. old_range . start + ( n as usize ) - ( x as usize ) , new , new_range . start .. new_range . start + ( m as usize ) - ( y as usize ) , ) ; x += common_suf_len as i32 ; y += common_suf_len as i32 ; } rev_front [ k ] = x ; // If delta is even and k is in the defined range, check for an overlap if ! is_odd && ( k - delta ) . abs ( ) <= d { let forward_x = fwd_front [ - ( k - delta ) ] ; // If forward_x + reverse_x >= n, the forward and backward paths make up a full // path, so we have a possible overlap. So return the furthest reaching reverse // path as the middle snake. // NOTE: that we can convert x and y to `usize` because they are both within // the range of the length of the inputs, which are valid usize values. if forward_x + x >= n { let old = n - x + ( old_range . start as i32 ) ; let new = m - y + ( new_range . start as i32 ) ; debug_assert ! ( old ( old_range start as i32 ) old ( old_range end as i32 ) " " old old_range start old_range end ) ; debug_assert ! ( new ( new_range start as i32 ) new ( new_range end as i32 ) " " new new_range start new_range end ) ; return Coordinates { old : old as usize , new : new as usize , } ; } } } } unreachable ! ( ) ; }
Calculate the (x, y) coordinates of the midpoint of the optimal path.
Calculate the ( x y ) coordinates of the midpoint of the optimal path .
old
&[T]
old_range
Range<usize>
new
&[T]
new_range
Range<usize>
frontiers
&mut MyersFrontiers
old
&[T]
old_range
Range<usize>
new
&[T]
new_range
Range<usize>
frontiers
&mut MyersFrontiers