You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					827 lines
				
				28 KiB
			
		
		
			
		
	
	
					827 lines
				
				28 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								'use strict';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Object.defineProperty(exports, '__esModule', {
							 | 
						||
| 
								 | 
							
								  value: true
							 | 
						||
| 
								 | 
							
								});
							 | 
						||
| 
								 | 
							
								exports.default = void 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This source code is licensed under the MIT license found in the
							 | 
						||
| 
								 | 
							
								 * LICENSE file in the root directory of this source tree.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								// This diff-sequences package implements the linear space variation in
							 | 
						||
| 
								 | 
							
								// An O(ND) Difference Algorithm and Its Variations by Eugene W. Myers
							 | 
						||
| 
								 | 
							
								// Relationship in notation between Myers paper and this package:
							 | 
						||
| 
								 | 
							
								// A is a
							 | 
						||
| 
								 | 
							
								// N is aLength, aEnd - aStart, and so on
							 | 
						||
| 
								 | 
							
								// x is aIndex, aFirst, aLast, and so on
							 | 
						||
| 
								 | 
							
								// B is b
							 | 
						||
| 
								 | 
							
								// M is bLength, bEnd - bStart, and so on
							 | 
						||
| 
								 | 
							
								// y is bIndex, bFirst, bLast, and so on
							 | 
						||
| 
								 | 
							
								// Δ = N - M is negative of baDeltaLength = bLength - aLength
							 | 
						||
| 
								 | 
							
								// D is d
							 | 
						||
| 
								 | 
							
								// k is kF
							 | 
						||
| 
								 | 
							
								// k + Δ is kF = kR - baDeltaLength
							 | 
						||
| 
								 | 
							
								// V is aIndexesF or aIndexesR (see comment below about Indexes type)
							 | 
						||
| 
								 | 
							
								// index intervals [1, N] and [1, M] are [0, aLength) and [0, bLength)
							 | 
						||
| 
								 | 
							
								// starting point in forward direction (0, 0) is (-1, -1)
							 | 
						||
| 
								 | 
							
								// starting point in reverse direction (N + 1, M + 1) is (aLength, bLength)
							 | 
						||
| 
								 | 
							
								// The “edit graph” for sequences a and b corresponds to items:
							 | 
						||
| 
								 | 
							
								// in a on the horizontal axis
							 | 
						||
| 
								 | 
							
								// in b on the vertical axis
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Given a-coordinate of a point in a diagonal, you can compute b-coordinate.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Forward diagonals kF:
							 | 
						||
| 
								 | 
							
								// zero diagonal intersects top left corner
							 | 
						||
| 
								 | 
							
								// positive diagonals intersect top edge
							 | 
						||
| 
								 | 
							
								// negative diagonals insersect left edge
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Reverse diagonals kR:
							 | 
						||
| 
								 | 
							
								// zero diagonal intersects bottom right corner
							 | 
						||
| 
								 | 
							
								// positive diagonals intersect right edge
							 | 
						||
| 
								 | 
							
								// negative diagonals intersect bottom edge
							 | 
						||
| 
								 | 
							
								// The graph contains a directed acyclic graph of edges:
							 | 
						||
| 
								 | 
							
								// horizontal: delete an item from a
							 | 
						||
| 
								 | 
							
								// vertical: insert an item from b
							 | 
						||
| 
								 | 
							
								// diagonal: common item in a and b
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// The algorithm solves dual problems in the graph analogy:
							 | 
						||
| 
								 | 
							
								// Find longest common subsequence: path with maximum number of diagonal edges
							 | 
						||
| 
								 | 
							
								// Find shortest edit script: path with minimum number of non-diagonal edges
							 | 
						||
| 
								 | 
							
								// Input callback function compares items at indexes in the sequences.
							 | 
						||
| 
								 | 
							
								// Output callback function receives the number of adjacent items
							 | 
						||
| 
								 | 
							
								// and starting indexes of each common subsequence.
							 | 
						||
| 
								 | 
							
								// Either original functions or wrapped to swap indexes if graph is transposed.
							 | 
						||
| 
								 | 
							
								// Indexes in sequence a of last point of forward or reverse paths in graph.
							 | 
						||
| 
								 | 
							
								// Myers algorithm indexes by diagonal k which for negative is bad deopt in V8.
							 | 
						||
| 
								 | 
							
								// This package indexes by iF and iR which are greater than or equal to zero.
							 | 
						||
| 
								 | 
							
								// and also updates the index arrays in place to cut memory in half.
							 | 
						||
| 
								 | 
							
								// kF = 2 * iF - d
							 | 
						||
| 
								 | 
							
								// kR = d - 2 * iR
							 | 
						||
| 
								 | 
							
								// Division of index intervals in sequences a and b at the middle change.
							 | 
						||
| 
								 | 
							
								// Invariant: intervals do not have common items at the start or end.
							 | 
						||
| 
								 | 
							
								const pkg = 'diff-sequences'; // for error messages
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const NOT_YET_SET = 0; // small int instead of undefined to avoid deopt in V8
							 | 
						||
| 
								 | 
							
								// Return the number of common items that follow in forward direction.
							 | 
						||
| 
								 | 
							
								// The length of what Myers paper calls a “snake” in a forward path.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const countCommonItemsF = (aIndex, aEnd, bIndex, bEnd, isCommon) => {
							 | 
						||
| 
								 | 
							
								  let nCommon = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  while (aIndex < aEnd && bIndex < bEnd && isCommon(aIndex, bIndex)) {
							 | 
						||
| 
								 | 
							
								    aIndex += 1;
							 | 
						||
| 
								 | 
							
								    bIndex += 1;
							 | 
						||
| 
								 | 
							
								    nCommon += 1;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return nCommon;
							 | 
						||
| 
								 | 
							
								}; // Return the number of common items that precede in reverse direction.
							 | 
						||
| 
								 | 
							
								// The length of what Myers paper calls a “snake” in a reverse path.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const countCommonItemsR = (aStart, aIndex, bStart, bIndex, isCommon) => {
							 | 
						||
| 
								 | 
							
								  let nCommon = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  while (aStart <= aIndex && bStart <= bIndex && isCommon(aIndex, bIndex)) {
							 | 
						||
| 
								 | 
							
								    aIndex -= 1;
							 | 
						||
| 
								 | 
							
								    bIndex -= 1;
							 | 
						||
| 
								 | 
							
								    nCommon += 1;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return nCommon;
							 | 
						||
| 
								 | 
							
								}; // A simple function to extend forward paths from (d - 1) to d changes
							 | 
						||
| 
								 | 
							
								// when forward and reverse paths cannot yet overlap.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const extendPathsF = (d, aEnd, bEnd, bF, isCommon, aIndexesF, iMaxF) => {
							 | 
						||
| 
								 | 
							
								  // Unroll the first iteration.
							 | 
						||
| 
								 | 
							
								  let iF = 0;
							 | 
						||
| 
								 | 
							
								  let kF = -d; // kF = 2 * iF - d
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  let aFirst = aIndexesF[iF]; // in first iteration always insert
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  let aIndexPrev1 = aFirst; // prev value of [iF - 1] in next iteration
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  aIndexesF[iF] += countCommonItemsF(
							 | 
						||
| 
								 | 
							
								    aFirst + 1,
							 | 
						||
| 
								 | 
							
								    aEnd,
							 | 
						||
| 
								 | 
							
								    bF + aFirst - kF + 1,
							 | 
						||
| 
								 | 
							
								    bEnd,
							 | 
						||
| 
								 | 
							
								    isCommon
							 | 
						||
| 
								 | 
							
								  ); // Optimization: skip diagonals in which paths cannot ever overlap.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const nF = d < iMaxF ? d : iMaxF; // The diagonals kF are odd when d is odd and even when d is even.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (iF += 1, kF += 2; iF <= nF; iF += 1, kF += 2) {
							 | 
						||
| 
								 | 
							
								    // To get first point of path segment, move one change in forward direction
							 | 
						||
| 
								 | 
							
								    // from last point of previous path segment in an adjacent diagonal.
							 | 
						||
| 
								 | 
							
								    // In last possible iteration when iF === d and kF === d always delete.
							 | 
						||
| 
								 | 
							
								    if (iF !== d && aIndexPrev1 < aIndexesF[iF]) {
							 | 
						||
| 
								 | 
							
								      aFirst = aIndexesF[iF]; // vertical to insert from b
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      aFirst = aIndexPrev1 + 1; // horizontal to delete from a
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (aEnd <= aFirst) {
							 | 
						||
| 
								 | 
							
								        // Optimization: delete moved past right of graph.
							 | 
						||
| 
								 | 
							
								        return iF - 1;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    } // To get last point of path segment, move along diagonal of common items.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    aIndexPrev1 = aIndexesF[iF];
							 | 
						||
| 
								 | 
							
								    aIndexesF[iF] =
							 | 
						||
| 
								 | 
							
								      aFirst +
							 | 
						||
| 
								 | 
							
								      countCommonItemsF(aFirst + 1, aEnd, bF + aFirst - kF + 1, bEnd, isCommon);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return iMaxF;
							 | 
						||
| 
								 | 
							
								}; // A simple function to extend reverse paths from (d - 1) to d changes
							 | 
						||
| 
								 | 
							
								// when reverse and forward paths cannot yet overlap.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const extendPathsR = (d, aStart, bStart, bR, isCommon, aIndexesR, iMaxR) => {
							 | 
						||
| 
								 | 
							
								  // Unroll the first iteration.
							 | 
						||
| 
								 | 
							
								  let iR = 0;
							 | 
						||
| 
								 | 
							
								  let kR = d; // kR = d - 2 * iR
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  let aFirst = aIndexesR[iR]; // in first iteration always insert
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  let aIndexPrev1 = aFirst; // prev value of [iR - 1] in next iteration
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  aIndexesR[iR] -= countCommonItemsR(
							 | 
						||
| 
								 | 
							
								    aStart,
							 | 
						||
| 
								 | 
							
								    aFirst - 1,
							 | 
						||
| 
								 | 
							
								    bStart,
							 | 
						||
| 
								 | 
							
								    bR + aFirst - kR - 1,
							 | 
						||
| 
								 | 
							
								    isCommon
							 | 
						||
| 
								 | 
							
								  ); // Optimization: skip diagonals in which paths cannot ever overlap.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const nR = d < iMaxR ? d : iMaxR; // The diagonals kR are odd when d is odd and even when d is even.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (iR += 1, kR -= 2; iR <= nR; iR += 1, kR -= 2) {
							 | 
						||
| 
								 | 
							
								    // To get first point of path segment, move one change in reverse direction
							 | 
						||
| 
								 | 
							
								    // from last point of previous path segment in an adjacent diagonal.
							 | 
						||
| 
								 | 
							
								    // In last possible iteration when iR === d and kR === -d always delete.
							 | 
						||
| 
								 | 
							
								    if (iR !== d && aIndexesR[iR] < aIndexPrev1) {
							 | 
						||
| 
								 | 
							
								      aFirst = aIndexesR[iR]; // vertical to insert from b
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      aFirst = aIndexPrev1 - 1; // horizontal to delete from a
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (aFirst < aStart) {
							 | 
						||
| 
								 | 
							
								        // Optimization: delete moved past left of graph.
							 | 
						||
| 
								 | 
							
								        return iR - 1;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    } // To get last point of path segment, move along diagonal of common items.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    aIndexPrev1 = aIndexesR[iR];
							 | 
						||
| 
								 | 
							
								    aIndexesR[iR] =
							 | 
						||
| 
								 | 
							
								      aFirst -
							 | 
						||
| 
								 | 
							
								      countCommonItemsR(
							 | 
						||
| 
								 | 
							
								        aStart,
							 | 
						||
| 
								 | 
							
								        aFirst - 1,
							 | 
						||
| 
								 | 
							
								        bStart,
							 | 
						||
| 
								 | 
							
								        bR + aFirst - kR - 1,
							 | 
						||
| 
								 | 
							
								        isCommon
							 | 
						||
| 
								 | 
							
								      );
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return iMaxR;
							 | 
						||
| 
								 | 
							
								}; // A complete function to extend forward paths from (d - 1) to d changes.
							 | 
						||
| 
								 | 
							
								// Return true if a path overlaps reverse path of (d - 1) changes in its diagonal.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const extendOverlappablePathsF = (
							 | 
						||
| 
								 | 
							
								  d,
							 | 
						||
| 
								 | 
							
								  aStart,
							 | 
						||
| 
								 | 
							
								  aEnd,
							 | 
						||
| 
								 | 
							
								  bStart,
							 | 
						||
| 
								 | 
							
								  bEnd,
							 | 
						||
| 
								 | 
							
								  isCommon,
							 | 
						||
| 
								 | 
							
								  aIndexesF,
							 | 
						||
| 
								 | 
							
								  iMaxF,
							 | 
						||
| 
								 | 
							
								  aIndexesR,
							 | 
						||
| 
								 | 
							
								  iMaxR,
							 | 
						||
| 
								 | 
							
								  division
							 | 
						||
| 
								 | 
							
								) => {
							 | 
						||
| 
								 | 
							
								  const bF = bStart - aStart; // bIndex = bF + aIndex - kF
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const aLength = aEnd - aStart;
							 | 
						||
| 
								 | 
							
								  const bLength = bEnd - bStart;
							 | 
						||
| 
								 | 
							
								  const baDeltaLength = bLength - aLength; // kF = kR - baDeltaLength
							 | 
						||
| 
								 | 
							
								  // Range of diagonals in which forward and reverse paths might overlap.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const kMinOverlapF = -baDeltaLength - (d - 1); // -(d - 1) <= kR
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const kMaxOverlapF = -baDeltaLength + (d - 1); // kR <= (d - 1)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  let aIndexPrev1 = NOT_YET_SET; // prev value of [iF - 1] in next iteration
							 | 
						||
| 
								 | 
							
								  // Optimization: skip diagonals in which paths cannot ever overlap.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const nF = d < iMaxF ? d : iMaxF; // The diagonals kF = 2 * iF - d are odd when d is odd and even when d is even.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (let iF = 0, kF = -d; iF <= nF; iF += 1, kF += 2) {
							 | 
						||
| 
								 | 
							
								    // To get first point of path segment, move one change in forward direction
							 | 
						||
| 
								 | 
							
								    // from last point of previous path segment in an adjacent diagonal.
							 | 
						||
| 
								 | 
							
								    // In first iteration when iF === 0 and kF === -d always insert.
							 | 
						||
| 
								 | 
							
								    // In last possible iteration when iF === d and kF === d always delete.
							 | 
						||
| 
								 | 
							
								    const insert = iF === 0 || (iF !== d && aIndexPrev1 < aIndexesF[iF]);
							 | 
						||
| 
								 | 
							
								    const aLastPrev = insert ? aIndexesF[iF] : aIndexPrev1;
							 | 
						||
| 
								 | 
							
								    const aFirst = insert
							 | 
						||
| 
								 | 
							
								      ? aLastPrev // vertical to insert from b
							 | 
						||
| 
								 | 
							
								      : aLastPrev + 1; // horizontal to delete from a
							 | 
						||
| 
								 | 
							
								    // To get last point of path segment, move along diagonal of common items.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const bFirst = bF + aFirst - kF;
							 | 
						||
| 
								 | 
							
								    const nCommonF = countCommonItemsF(
							 | 
						||
| 
								 | 
							
								      aFirst + 1,
							 | 
						||
| 
								 | 
							
								      aEnd,
							 | 
						||
| 
								 | 
							
								      bFirst + 1,
							 | 
						||
| 
								 | 
							
								      bEnd,
							 | 
						||
| 
								 | 
							
								      isCommon
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								    const aLast = aFirst + nCommonF;
							 | 
						||
| 
								 | 
							
								    aIndexPrev1 = aIndexesF[iF];
							 | 
						||
| 
								 | 
							
								    aIndexesF[iF] = aLast;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (kMinOverlapF <= kF && kF <= kMaxOverlapF) {
							 | 
						||
| 
								 | 
							
								      // Solve for iR of reverse path with (d - 1) changes in diagonal kF:
							 | 
						||
| 
								 | 
							
								      // kR = kF + baDeltaLength
							 | 
						||
| 
								 | 
							
								      // kR = (d - 1) - 2 * iR
							 | 
						||
| 
								 | 
							
								      const iR = (d - 1 - (kF + baDeltaLength)) / 2; // If this forward path overlaps the reverse path in this diagonal,
							 | 
						||
| 
								 | 
							
								      // then this is the middle change of the index intervals.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (iR <= iMaxR && aIndexesR[iR] - 1 <= aLast) {
							 | 
						||
| 
								 | 
							
								        // Unlike the Myers algorithm which finds only the middle “snake”
							 | 
						||
| 
								 | 
							
								        // this package can find two common subsequences per division.
							 | 
						||
| 
								 | 
							
								        // Last point of previous path segment is on an adjacent diagonal.
							 | 
						||
| 
								 | 
							
								        const bLastPrev = bF + aLastPrev - (insert ? kF + 1 : kF - 1); // Because of invariant that intervals preceding the middle change
							 | 
						||
| 
								 | 
							
								        // cannot have common items at the end,
							 | 
						||
| 
								 | 
							
								        // move in reverse direction along a diagonal of common items.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const nCommonR = countCommonItemsR(
							 | 
						||
| 
								 | 
							
								          aStart,
							 | 
						||
| 
								 | 
							
								          aLastPrev,
							 | 
						||
| 
								 | 
							
								          bStart,
							 | 
						||
| 
								 | 
							
								          bLastPrev,
							 | 
						||
| 
								 | 
							
								          isCommon
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								        const aIndexPrevFirst = aLastPrev - nCommonR;
							 | 
						||
| 
								 | 
							
								        const bIndexPrevFirst = bLastPrev - nCommonR;
							 | 
						||
| 
								 | 
							
								        const aEndPreceding = aIndexPrevFirst + 1;
							 | 
						||
| 
								 | 
							
								        const bEndPreceding = bIndexPrevFirst + 1;
							 | 
						||
| 
								 | 
							
								        division.nChangePreceding = d - 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (d - 1 === aEndPreceding + bEndPreceding - aStart - bStart) {
							 | 
						||
| 
								 | 
							
								          // Optimization: number of preceding changes in forward direction
							 | 
						||
| 
								 | 
							
								          // is equal to number of items in preceding interval,
							 | 
						||
| 
								 | 
							
								          // therefore it cannot contain any common items.
							 | 
						||
| 
								 | 
							
								          division.aEndPreceding = aStart;
							 | 
						||
| 
								 | 
							
								          division.bEndPreceding = bStart;
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								          division.aEndPreceding = aEndPreceding;
							 | 
						||
| 
								 | 
							
								          division.bEndPreceding = bEndPreceding;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        division.nCommonPreceding = nCommonR;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (nCommonR !== 0) {
							 | 
						||
| 
								 | 
							
								          division.aCommonPreceding = aEndPreceding;
							 | 
						||
| 
								 | 
							
								          division.bCommonPreceding = bEndPreceding;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        division.nCommonFollowing = nCommonF;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (nCommonF !== 0) {
							 | 
						||
| 
								 | 
							
								          division.aCommonFollowing = aFirst + 1;
							 | 
						||
| 
								 | 
							
								          division.bCommonFollowing = bFirst + 1;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const aStartFollowing = aLast + 1;
							 | 
						||
| 
								 | 
							
								        const bStartFollowing = bFirst + nCommonF + 1;
							 | 
						||
| 
								 | 
							
								        division.nChangeFollowing = d - 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (d - 1 === aEnd + bEnd - aStartFollowing - bStartFollowing) {
							 | 
						||
| 
								 | 
							
								          // Optimization: number of changes in reverse direction
							 | 
						||
| 
								 | 
							
								          // is equal to number of items in following interval,
							 | 
						||
| 
								 | 
							
								          // therefore it cannot contain any common items.
							 | 
						||
| 
								 | 
							
								          division.aStartFollowing = aEnd;
							 | 
						||
| 
								 | 
							
								          division.bStartFollowing = bEnd;
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								          division.aStartFollowing = aStartFollowing;
							 | 
						||
| 
								 | 
							
								          division.bStartFollowing = bStartFollowing;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return true;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return false;
							 | 
						||
| 
								 | 
							
								}; // A complete function to extend reverse paths from (d - 1) to d changes.
							 | 
						||
| 
								 | 
							
								// Return true if a path overlaps forward path of d changes in its diagonal.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const extendOverlappablePathsR = (
							 | 
						||
| 
								 | 
							
								  d,
							 | 
						||
| 
								 | 
							
								  aStart,
							 | 
						||
| 
								 | 
							
								  aEnd,
							 | 
						||
| 
								 | 
							
								  bStart,
							 | 
						||
| 
								 | 
							
								  bEnd,
							 | 
						||
| 
								 | 
							
								  isCommon,
							 | 
						||
| 
								 | 
							
								  aIndexesF,
							 | 
						||
| 
								 | 
							
								  iMaxF,
							 | 
						||
| 
								 | 
							
								  aIndexesR,
							 | 
						||
| 
								 | 
							
								  iMaxR,
							 | 
						||
| 
								 | 
							
								  division
							 | 
						||
| 
								 | 
							
								) => {
							 | 
						||
| 
								 | 
							
								  const bR = bEnd - aEnd; // bIndex = bR + aIndex - kR
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const aLength = aEnd - aStart;
							 | 
						||
| 
								 | 
							
								  const bLength = bEnd - bStart;
							 | 
						||
| 
								 | 
							
								  const baDeltaLength = bLength - aLength; // kR = kF + baDeltaLength
							 | 
						||
| 
								 | 
							
								  // Range of diagonals in which forward and reverse paths might overlap.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const kMinOverlapR = baDeltaLength - d; // -d <= kF
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const kMaxOverlapR = baDeltaLength + d; // kF <= d
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  let aIndexPrev1 = NOT_YET_SET; // prev value of [iR - 1] in next iteration
							 | 
						||
| 
								 | 
							
								  // Optimization: skip diagonals in which paths cannot ever overlap.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const nR = d < iMaxR ? d : iMaxR; // The diagonals kR = d - 2 * iR are odd when d is odd and even when d is even.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (let iR = 0, kR = d; iR <= nR; iR += 1, kR -= 2) {
							 | 
						||
| 
								 | 
							
								    // To get first point of path segment, move one change in reverse direction
							 | 
						||
| 
								 | 
							
								    // from last point of previous path segment in an adjacent diagonal.
							 | 
						||
| 
								 | 
							
								    // In first iteration when iR === 0 and kR === d always insert.
							 | 
						||
| 
								 | 
							
								    // In last possible iteration when iR === d and kR === -d always delete.
							 | 
						||
| 
								 | 
							
								    const insert = iR === 0 || (iR !== d && aIndexesR[iR] < aIndexPrev1);
							 | 
						||
| 
								 | 
							
								    const aLastPrev = insert ? aIndexesR[iR] : aIndexPrev1;
							 | 
						||
| 
								 | 
							
								    const aFirst = insert
							 | 
						||
| 
								 | 
							
								      ? aLastPrev // vertical to insert from b
							 | 
						||
| 
								 | 
							
								      : aLastPrev - 1; // horizontal to delete from a
							 | 
						||
| 
								 | 
							
								    // To get last point of path segment, move along diagonal of common items.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const bFirst = bR + aFirst - kR;
							 | 
						||
| 
								 | 
							
								    const nCommonR = countCommonItemsR(
							 | 
						||
| 
								 | 
							
								      aStart,
							 | 
						||
| 
								 | 
							
								      aFirst - 1,
							 | 
						||
| 
								 | 
							
								      bStart,
							 | 
						||
| 
								 | 
							
								      bFirst - 1,
							 | 
						||
| 
								 | 
							
								      isCommon
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								    const aLast = aFirst - nCommonR;
							 | 
						||
| 
								 | 
							
								    aIndexPrev1 = aIndexesR[iR];
							 | 
						||
| 
								 | 
							
								    aIndexesR[iR] = aLast;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (kMinOverlapR <= kR && kR <= kMaxOverlapR) {
							 | 
						||
| 
								 | 
							
								      // Solve for iF of forward path with d changes in diagonal kR:
							 | 
						||
| 
								 | 
							
								      // kF = kR - baDeltaLength
							 | 
						||
| 
								 | 
							
								      // kF = 2 * iF - d
							 | 
						||
| 
								 | 
							
								      const iF = (d + (kR - baDeltaLength)) / 2; // If this reverse path overlaps the forward path in this diagonal,
							 | 
						||
| 
								 | 
							
								      // then this is a middle change of the index intervals.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (iF <= iMaxF && aLast - 1 <= aIndexesF[iF]) {
							 | 
						||
| 
								 | 
							
								        const bLast = bFirst - nCommonR;
							 | 
						||
| 
								 | 
							
								        division.nChangePreceding = d;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (d === aLast + bLast - aStart - bStart) {
							 | 
						||
| 
								 | 
							
								          // Optimization: number of changes in reverse direction
							 | 
						||
| 
								 | 
							
								          // is equal to number of items in preceding interval,
							 | 
						||
| 
								 | 
							
								          // therefore it cannot contain any common items.
							 | 
						||
| 
								 | 
							
								          division.aEndPreceding = aStart;
							 | 
						||
| 
								 | 
							
								          division.bEndPreceding = bStart;
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								          division.aEndPreceding = aLast;
							 | 
						||
| 
								 | 
							
								          division.bEndPreceding = bLast;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        division.nCommonPreceding = nCommonR;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (nCommonR !== 0) {
							 | 
						||
| 
								 | 
							
								          // The last point of reverse path segment is start of common subsequence.
							 | 
						||
| 
								 | 
							
								          division.aCommonPreceding = aLast;
							 | 
						||
| 
								 | 
							
								          division.bCommonPreceding = bLast;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        division.nChangeFollowing = d - 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (d === 1) {
							 | 
						||
| 
								 | 
							
								          // There is no previous path segment.
							 | 
						||
| 
								 | 
							
								          division.nCommonFollowing = 0;
							 | 
						||
| 
								 | 
							
								          division.aStartFollowing = aEnd;
							 | 
						||
| 
								 | 
							
								          division.bStartFollowing = bEnd;
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								          // Unlike the Myers algorithm which finds only the middle “snake”
							 | 
						||
| 
								 | 
							
								          // this package can find two common subsequences per division.
							 | 
						||
| 
								 | 
							
								          // Last point of previous path segment is on an adjacent diagonal.
							 | 
						||
| 
								 | 
							
								          const bLastPrev = bR + aLastPrev - (insert ? kR - 1 : kR + 1); // Because of invariant that intervals following the middle change
							 | 
						||
| 
								 | 
							
								          // cannot have common items at the start,
							 | 
						||
| 
								 | 
							
								          // move in forward direction along a diagonal of common items.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          const nCommonF = countCommonItemsF(
							 | 
						||
| 
								 | 
							
								            aLastPrev,
							 | 
						||
| 
								 | 
							
								            aEnd,
							 | 
						||
| 
								 | 
							
								            bLastPrev,
							 | 
						||
| 
								 | 
							
								            bEnd,
							 | 
						||
| 
								 | 
							
								            isCommon
							 | 
						||
| 
								 | 
							
								          );
							 | 
						||
| 
								 | 
							
								          division.nCommonFollowing = nCommonF;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          if (nCommonF !== 0) {
							 | 
						||
| 
								 | 
							
								            // The last point of reverse path segment is start of common subsequence.
							 | 
						||
| 
								 | 
							
								            division.aCommonFollowing = aLastPrev;
							 | 
						||
| 
								 | 
							
								            division.bCommonFollowing = bLastPrev;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          const aStartFollowing = aLastPrev + nCommonF; // aFirstPrev
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          const bStartFollowing = bLastPrev + nCommonF; // bFirstPrev
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          if (d - 1 === aEnd + bEnd - aStartFollowing - bStartFollowing) {
							 | 
						||
| 
								 | 
							
								            // Optimization: number of changes in forward direction
							 | 
						||
| 
								 | 
							
								            // is equal to number of items in following interval,
							 | 
						||
| 
								 | 
							
								            // therefore it cannot contain any common items.
							 | 
						||
| 
								 | 
							
								            division.aStartFollowing = aEnd;
							 | 
						||
| 
								 | 
							
								            division.bStartFollowing = bEnd;
							 | 
						||
| 
								 | 
							
								          } else {
							 | 
						||
| 
								 | 
							
								            division.aStartFollowing = aStartFollowing;
							 | 
						||
| 
								 | 
							
								            division.bStartFollowing = bStartFollowing;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return true;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return false;
							 | 
						||
| 
								 | 
							
								}; // Given index intervals and input function to compare items at indexes,
							 | 
						||
| 
								 | 
							
								// divide at the middle change.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// DO NOT CALL if start === end, because interval cannot contain common items
							 | 
						||
| 
								 | 
							
								// and because this function will throw the “no overlap” error.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const divide = (
							 | 
						||
| 
								 | 
							
								  nChange,
							 | 
						||
| 
								 | 
							
								  aStart,
							 | 
						||
| 
								 | 
							
								  aEnd,
							 | 
						||
| 
								 | 
							
								  bStart,
							 | 
						||
| 
								 | 
							
								  bEnd,
							 | 
						||
| 
								 | 
							
								  isCommon,
							 | 
						||
| 
								 | 
							
								  aIndexesF,
							 | 
						||
| 
								 | 
							
								  aIndexesR,
							 | 
						||
| 
								 | 
							
								  division // output
							 | 
						||
| 
								 | 
							
								) => {
							 | 
						||
| 
								 | 
							
								  const bF = bStart - aStart; // bIndex = bF + aIndex - kF
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const bR = bEnd - aEnd; // bIndex = bR + aIndex - kR
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const aLength = aEnd - aStart;
							 | 
						||
| 
								 | 
							
								  const bLength = bEnd - bStart; // Because graph has square or portrait orientation,
							 | 
						||
| 
								 | 
							
								  // length difference is minimum number of items to insert from b.
							 | 
						||
| 
								 | 
							
								  // Corresponding forward and reverse diagonals in graph
							 | 
						||
| 
								 | 
							
								  // depend on length difference of the sequences:
							 | 
						||
| 
								 | 
							
								  // kF = kR - baDeltaLength
							 | 
						||
| 
								 | 
							
								  // kR = kF + baDeltaLength
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const baDeltaLength = bLength - aLength; // Optimization: max diagonal in graph intersects corner of shorter side.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  let iMaxF = aLength;
							 | 
						||
| 
								 | 
							
								  let iMaxR = aLength; // Initialize no changes yet in forward or reverse direction:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  aIndexesF[0] = aStart - 1; // at open start of interval, outside closed start
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  aIndexesR[0] = aEnd; // at open end of interval
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (baDeltaLength % 2 === 0) {
							 | 
						||
| 
								 | 
							
								    // The number of changes in paths is 2 * d if length difference is even.
							 | 
						||
| 
								 | 
							
								    const dMin = (nChange || baDeltaLength) / 2;
							 | 
						||
| 
								 | 
							
								    const dMax = (aLength + bLength) / 2;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (let d = 1; d <= dMax; d += 1) {
							 | 
						||
| 
								 | 
							
								      iMaxF = extendPathsF(d, aEnd, bEnd, bF, isCommon, aIndexesF, iMaxF);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (d < dMin) {
							 | 
						||
| 
								 | 
							
								        iMaxR = extendPathsR(d, aStart, bStart, bR, isCommon, aIndexesR, iMaxR);
							 | 
						||
| 
								 | 
							
								      } else if (
							 | 
						||
| 
								 | 
							
								        // If a reverse path overlaps a forward path in the same diagonal,
							 | 
						||
| 
								 | 
							
								        // return a division of the index intervals at the middle change.
							 | 
						||
| 
								 | 
							
								        extendOverlappablePathsR(
							 | 
						||
| 
								 | 
							
								          d,
							 | 
						||
| 
								 | 
							
								          aStart,
							 | 
						||
| 
								 | 
							
								          aEnd,
							 | 
						||
| 
								 | 
							
								          bStart,
							 | 
						||
| 
								 | 
							
								          bEnd,
							 | 
						||
| 
								 | 
							
								          isCommon,
							 | 
						||
| 
								 | 
							
								          aIndexesF,
							 | 
						||
| 
								 | 
							
								          iMaxF,
							 | 
						||
| 
								 | 
							
								          aIndexesR,
							 | 
						||
| 
								 | 
							
								          iMaxR,
							 | 
						||
| 
								 | 
							
								          division
							 | 
						||
| 
								 | 
							
								        )
							 | 
						||
| 
								 | 
							
								      ) {
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    // The number of changes in paths is 2 * d - 1 if length difference is odd.
							 | 
						||
| 
								 | 
							
								    const dMin = ((nChange || baDeltaLength) + 1) / 2;
							 | 
						||
| 
								 | 
							
								    const dMax = (aLength + bLength + 1) / 2; // Unroll first half iteration so loop extends the relevant pairs of paths.
							 | 
						||
| 
								 | 
							
								    // Because of invariant that intervals have no common items at start or end,
							 | 
						||
| 
								 | 
							
								    // and limitation not to call divide with empty intervals,
							 | 
						||
| 
								 | 
							
								    // therefore it cannot be called if a forward path with one change
							 | 
						||
| 
								 | 
							
								    // would overlap a reverse path with no changes, even if dMin === 1.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    let d = 1;
							 | 
						||
| 
								 | 
							
								    iMaxF = extendPathsF(d, aEnd, bEnd, bF, isCommon, aIndexesF, iMaxF);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (d += 1; d <= dMax; d += 1) {
							 | 
						||
| 
								 | 
							
								      iMaxR = extendPathsR(
							 | 
						||
| 
								 | 
							
								        d - 1,
							 | 
						||
| 
								 | 
							
								        aStart,
							 | 
						||
| 
								 | 
							
								        bStart,
							 | 
						||
| 
								 | 
							
								        bR,
							 | 
						||
| 
								 | 
							
								        isCommon,
							 | 
						||
| 
								 | 
							
								        aIndexesR,
							 | 
						||
| 
								 | 
							
								        iMaxR
							 | 
						||
| 
								 | 
							
								      );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (d < dMin) {
							 | 
						||
| 
								 | 
							
								        iMaxF = extendPathsF(d, aEnd, bEnd, bF, isCommon, aIndexesF, iMaxF);
							 | 
						||
| 
								 | 
							
								      } else if (
							 | 
						||
| 
								 | 
							
								        // If a forward path overlaps a reverse path in the same diagonal,
							 | 
						||
| 
								 | 
							
								        // return a division of the index intervals at the middle change.
							 | 
						||
| 
								 | 
							
								        extendOverlappablePathsF(
							 | 
						||
| 
								 | 
							
								          d,
							 | 
						||
| 
								 | 
							
								          aStart,
							 | 
						||
| 
								 | 
							
								          aEnd,
							 | 
						||
| 
								 | 
							
								          bStart,
							 | 
						||
| 
								 | 
							
								          bEnd,
							 | 
						||
| 
								 | 
							
								          isCommon,
							 | 
						||
| 
								 | 
							
								          aIndexesF,
							 | 
						||
| 
								 | 
							
								          iMaxF,
							 | 
						||
| 
								 | 
							
								          aIndexesR,
							 | 
						||
| 
								 | 
							
								          iMaxR,
							 | 
						||
| 
								 | 
							
								          division
							 | 
						||
| 
								 | 
							
								        )
							 | 
						||
| 
								 | 
							
								      ) {
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  /* istanbul ignore next */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  throw new Error(
							 | 
						||
| 
								 | 
							
								    `${pkg}: no overlap aStart=${aStart} aEnd=${aEnd} bStart=${bStart} bEnd=${bEnd}`
							 | 
						||
| 
								 | 
							
								  );
							 | 
						||
| 
								 | 
							
								}; // Given index intervals and input function to compare items at indexes,
							 | 
						||
| 
								 | 
							
								// return by output function the number of adjacent items and starting indexes
							 | 
						||
| 
								 | 
							
								// of each common subsequence. Divide and conquer with only linear space.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// The index intervals are half open [start, end) like array slice method.
							 | 
						||
| 
								 | 
							
								// DO NOT CALL if start === end, because interval cannot contain common items
							 | 
						||
| 
								 | 
							
								// and because divide function will throw the “no overlap” error.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const findSubsequences = (
							 | 
						||
| 
								 | 
							
								  nChange,
							 | 
						||
| 
								 | 
							
								  aStart,
							 | 
						||
| 
								 | 
							
								  aEnd,
							 | 
						||
| 
								 | 
							
								  bStart,
							 | 
						||
| 
								 | 
							
								  bEnd,
							 | 
						||
| 
								 | 
							
								  transposed,
							 | 
						||
| 
								 | 
							
								  callbacks,
							 | 
						||
| 
								 | 
							
								  aIndexesF,
							 | 
						||
| 
								 | 
							
								  aIndexesR,
							 | 
						||
| 
								 | 
							
								  division // temporary memory, not input nor output
							 | 
						||
| 
								 | 
							
								) => {
							 | 
						||
| 
								 | 
							
								  if (bEnd - bStart < aEnd - aStart) {
							 | 
						||
| 
								 | 
							
								    // Transpose graph so it has portrait instead of landscape orientation.
							 | 
						||
| 
								 | 
							
								    // Always compare shorter to longer sequence for consistency and optimization.
							 | 
						||
| 
								 | 
							
								    transposed = !transposed;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (transposed && callbacks.length === 1) {
							 | 
						||
| 
								 | 
							
								      // Lazily wrap callback functions to swap args if graph is transposed.
							 | 
						||
| 
								 | 
							
								      const _callbacks$ = callbacks[0],
							 | 
						||
| 
								 | 
							
								        foundSubsequence = _callbacks$.foundSubsequence,
							 | 
						||
| 
								 | 
							
								        isCommon = _callbacks$.isCommon;
							 | 
						||
| 
								 | 
							
								      callbacks[1] = {
							 | 
						||
| 
								 | 
							
								        foundSubsequence: (function(_foundSubsequence) {
							 | 
						||
| 
								 | 
							
								          function foundSubsequence(_x, _x2, _x3) {
							 | 
						||
| 
								 | 
							
								            return _foundSubsequence.apply(this, arguments);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          foundSubsequence.toString = function() {
							 | 
						||
| 
								 | 
							
								            return _foundSubsequence.toString();
							 | 
						||
| 
								 | 
							
								          };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          return foundSubsequence;
							 | 
						||
| 
								 | 
							
								        })((nCommon, bCommon, aCommon) => {
							 | 
						||
| 
								 | 
							
								          foundSubsequence(nCommon, aCommon, bCommon);
							 | 
						||
| 
								 | 
							
								        }),
							 | 
						||
| 
								 | 
							
								        isCommon: (function(_isCommon) {
							 | 
						||
| 
								 | 
							
								          function isCommon(_x4, _x5) {
							 | 
						||
| 
								 | 
							
								            return _isCommon.apply(this, arguments);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          isCommon.toString = function() {
							 | 
						||
| 
								 | 
							
								            return _isCommon.toString();
							 | 
						||
| 
								 | 
							
								          };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          return isCommon;
							 | 
						||
| 
								 | 
							
								        })((bIndex, aIndex) => isCommon(aIndex, bIndex))
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const tStart = aStart;
							 | 
						||
| 
								 | 
							
								    const tEnd = aEnd;
							 | 
						||
| 
								 | 
							
								    aStart = bStart;
							 | 
						||
| 
								 | 
							
								    aEnd = bEnd;
							 | 
						||
| 
								 | 
							
								    bStart = tStart;
							 | 
						||
| 
								 | 
							
								    bEnd = tEnd;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const _callbacks = callbacks[transposed ? 1 : 0],
							 | 
						||
| 
								 | 
							
								    foundSubsequence = _callbacks.foundSubsequence,
							 | 
						||
| 
								 | 
							
								    isCommon = _callbacks.isCommon; // Divide the index intervals at the middle change.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  divide(
							 | 
						||
| 
								 | 
							
								    nChange,
							 | 
						||
| 
								 | 
							
								    aStart,
							 | 
						||
| 
								 | 
							
								    aEnd,
							 | 
						||
| 
								 | 
							
								    bStart,
							 | 
						||
| 
								 | 
							
								    bEnd,
							 | 
						||
| 
								 | 
							
								    isCommon,
							 | 
						||
| 
								 | 
							
								    aIndexesF,
							 | 
						||
| 
								 | 
							
								    aIndexesR,
							 | 
						||
| 
								 | 
							
								    division
							 | 
						||
| 
								 | 
							
								  );
							 | 
						||
| 
								 | 
							
								  const nChangePreceding = division.nChangePreceding,
							 | 
						||
| 
								 | 
							
								    aEndPreceding = division.aEndPreceding,
							 | 
						||
| 
								 | 
							
								    bEndPreceding = division.bEndPreceding,
							 | 
						||
| 
								 | 
							
								    nCommonPreceding = division.nCommonPreceding,
							 | 
						||
| 
								 | 
							
								    aCommonPreceding = division.aCommonPreceding,
							 | 
						||
| 
								 | 
							
								    bCommonPreceding = division.bCommonPreceding,
							 | 
						||
| 
								 | 
							
								    nCommonFollowing = division.nCommonFollowing,
							 | 
						||
| 
								 | 
							
								    aCommonFollowing = division.aCommonFollowing,
							 | 
						||
| 
								 | 
							
								    bCommonFollowing = division.bCommonFollowing,
							 | 
						||
| 
								 | 
							
								    nChangeFollowing = division.nChangeFollowing,
							 | 
						||
| 
								 | 
							
								    aStartFollowing = division.aStartFollowing,
							 | 
						||
| 
								 | 
							
								    bStartFollowing = division.bStartFollowing; // Unless either index interval is empty, they might contain common items.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (aStart < aEndPreceding && bStart < bEndPreceding) {
							 | 
						||
| 
								 | 
							
								    // Recursely find and return common subsequences preceding the division.
							 | 
						||
| 
								 | 
							
								    findSubsequences(
							 | 
						||
| 
								 | 
							
								      nChangePreceding,
							 | 
						||
| 
								 | 
							
								      aStart,
							 | 
						||
| 
								 | 
							
								      aEndPreceding,
							 | 
						||
| 
								 | 
							
								      bStart,
							 | 
						||
| 
								 | 
							
								      bEndPreceding,
							 | 
						||
| 
								 | 
							
								      transposed,
							 | 
						||
| 
								 | 
							
								      callbacks,
							 | 
						||
| 
								 | 
							
								      aIndexesF,
							 | 
						||
| 
								 | 
							
								      aIndexesR,
							 | 
						||
| 
								 | 
							
								      division
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								  } // Return common subsequences that are adjacent to the middle change.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (nCommonPreceding !== 0) {
							 | 
						||
| 
								 | 
							
								    foundSubsequence(nCommonPreceding, aCommonPreceding, bCommonPreceding);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (nCommonFollowing !== 0) {
							 | 
						||
| 
								 | 
							
								    foundSubsequence(nCommonFollowing, aCommonFollowing, bCommonFollowing);
							 | 
						||
| 
								 | 
							
								  } // Unless either index interval is empty, they might contain common items.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (aStartFollowing < aEnd && bStartFollowing < bEnd) {
							 | 
						||
| 
								 | 
							
								    // Recursely find and return common subsequences following the division.
							 | 
						||
| 
								 | 
							
								    findSubsequences(
							 | 
						||
| 
								 | 
							
								      nChangeFollowing,
							 | 
						||
| 
								 | 
							
								      aStartFollowing,
							 | 
						||
| 
								 | 
							
								      aEnd,
							 | 
						||
| 
								 | 
							
								      bStartFollowing,
							 | 
						||
| 
								 | 
							
								      bEnd,
							 | 
						||
| 
								 | 
							
								      transposed,
							 | 
						||
| 
								 | 
							
								      callbacks,
							 | 
						||
| 
								 | 
							
								      aIndexesF,
							 | 
						||
| 
								 | 
							
								      aIndexesR,
							 | 
						||
| 
								 | 
							
								      division
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const validateLength = (name, arg) => {
							 | 
						||
| 
								 | 
							
								  const type = typeof arg;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (type !== 'number') {
							 | 
						||
| 
								 | 
							
								    throw new TypeError(`${pkg}: ${name} typeof ${type} is not a number`);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (!Number.isSafeInteger(arg)) {
							 | 
						||
| 
								 | 
							
								    throw new RangeError(`${pkg}: ${name} value ${arg} is not a safe integer`);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (arg < 0) {
							 | 
						||
| 
								 | 
							
								    throw new RangeError(`${pkg}: ${name} value ${arg} is a negative integer`);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const validateCallback = (name, arg) => {
							 | 
						||
| 
								 | 
							
								  const type = typeof arg;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (type !== 'function') {
							 | 
						||
| 
								 | 
							
								    throw new TypeError(`${pkg}: ${name} typeof ${type} is not a function`);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}; // Compare items in two sequences to find a longest common subsequence.
							 | 
						||
| 
								 | 
							
								// Given lengths of sequences and input function to compare items at indexes,
							 | 
						||
| 
								 | 
							
								// return by output function the number of adjacent items and starting indexes
							 | 
						||
| 
								 | 
							
								// of each common subsequence.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _default = (aLength, bLength, isCommon, foundSubsequence) => {
							 | 
						||
| 
								 | 
							
								  validateLength('aLength', aLength);
							 | 
						||
| 
								 | 
							
								  validateLength('bLength', bLength);
							 | 
						||
| 
								 | 
							
								  validateCallback('isCommon', isCommon);
							 | 
						||
| 
								 | 
							
								  validateCallback('foundSubsequence', foundSubsequence); // Count common items from the start in the forward direction.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const nCommonF = countCommonItemsF(0, aLength, 0, bLength, isCommon);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (nCommonF !== 0) {
							 | 
						||
| 
								 | 
							
								    foundSubsequence(nCommonF, 0, 0);
							 | 
						||
| 
								 | 
							
								  } // Unless both sequences consist of common items only,
							 | 
						||
| 
								 | 
							
								  // find common items in the half-trimmed index intervals.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (aLength !== nCommonF || bLength !== nCommonF) {
							 | 
						||
| 
								 | 
							
								    // Invariant: intervals do not have common items at the start.
							 | 
						||
| 
								 | 
							
								    // The start of an index interval is closed like array slice method.
							 | 
						||
| 
								 | 
							
								    const aStart = nCommonF;
							 | 
						||
| 
								 | 
							
								    const bStart = nCommonF; // Count common items from the end in the reverse direction.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const nCommonR = countCommonItemsR(
							 | 
						||
| 
								 | 
							
								      aStart,
							 | 
						||
| 
								 | 
							
								      aLength - 1,
							 | 
						||
| 
								 | 
							
								      bStart,
							 | 
						||
| 
								 | 
							
								      bLength - 1,
							 | 
						||
| 
								 | 
							
								      isCommon
							 | 
						||
| 
								 | 
							
								    ); // Invariant: intervals do not have common items at the end.
							 | 
						||
| 
								 | 
							
								    // The end of an index interval is open like array slice method.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const aEnd = aLength - nCommonR;
							 | 
						||
| 
								 | 
							
								    const bEnd = bLength - nCommonR; // Unless one sequence consists of common items only,
							 | 
						||
| 
								 | 
							
								    // therefore the other trimmed index interval consists of changes only,
							 | 
						||
| 
								 | 
							
								    // find common items in the trimmed index intervals.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const nCommonFR = nCommonF + nCommonR;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (aLength !== nCommonFR && bLength !== nCommonFR) {
							 | 
						||
| 
								 | 
							
								      const nChange = 0; // number of change items is not yet known
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      const transposed = false; // call the original unwrapped functions
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      const callbacks = [
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          foundSubsequence,
							 | 
						||
| 
								 | 
							
								          isCommon
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      ]; // Indexes in sequence a of last points in furthest reaching paths
							 | 
						||
| 
								 | 
							
								      // from outside the start at top left in the forward direction:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      const aIndexesF = [NOT_YET_SET]; // from the end at bottom right in the reverse direction:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      const aIndexesR = [NOT_YET_SET]; // Initialize one object as output of all calls to divide function.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      const division = {
							 | 
						||
| 
								 | 
							
								        aCommonFollowing: NOT_YET_SET,
							 | 
						||
| 
								 | 
							
								        aCommonPreceding: NOT_YET_SET,
							 | 
						||
| 
								 | 
							
								        aEndPreceding: NOT_YET_SET,
							 | 
						||
| 
								 | 
							
								        aStartFollowing: NOT_YET_SET,
							 | 
						||
| 
								 | 
							
								        bCommonFollowing: NOT_YET_SET,
							 | 
						||
| 
								 | 
							
								        bCommonPreceding: NOT_YET_SET,
							 | 
						||
| 
								 | 
							
								        bEndPreceding: NOT_YET_SET,
							 | 
						||
| 
								 | 
							
								        bStartFollowing: NOT_YET_SET,
							 | 
						||
| 
								 | 
							
								        nChangeFollowing: NOT_YET_SET,
							 | 
						||
| 
								 | 
							
								        nChangePreceding: NOT_YET_SET,
							 | 
						||
| 
								 | 
							
								        nCommonFollowing: NOT_YET_SET,
							 | 
						||
| 
								 | 
							
								        nCommonPreceding: NOT_YET_SET
							 | 
						||
| 
								 | 
							
								      }; // Find and return common subsequences in the trimmed index intervals.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      findSubsequences(
							 | 
						||
| 
								 | 
							
								        nChange,
							 | 
						||
| 
								 | 
							
								        aStart,
							 | 
						||
| 
								 | 
							
								        aEnd,
							 | 
						||
| 
								 | 
							
								        bStart,
							 | 
						||
| 
								 | 
							
								        bEnd,
							 | 
						||
| 
								 | 
							
								        transposed,
							 | 
						||
| 
								 | 
							
								        callbacks,
							 | 
						||
| 
								 | 
							
								        aIndexesF,
							 | 
						||
| 
								 | 
							
								        aIndexesR,
							 | 
						||
| 
								 | 
							
								        division
							 | 
						||
| 
								 | 
							
								      );
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (nCommonR !== 0) {
							 | 
						||
| 
								 | 
							
								      foundSubsequence(nCommonR, aEnd, bEnd);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								exports.default = _default;
							 |