UNPKG

extra-bigint

Version:

A [BigInt] can represent whole numbers larger than 2⁵³ - 1 [(1)].<br>

683 lines • 61.4 kB
// METHODS
// =======
// ABOUT
// -----
/**
 * Check if value is a bigint.
 * @param x a value
 * @returns is bigint?
 */ export function is(x) {
  return typeof x === "bigint";
}
// COMPARE
// -------
/**
 * Compare two bigints.
 * @param x a bigint
 * @param y another bigint
 * @returns x<y: -ve, x=y: 0, x>y: +ve
 */ export function compare(x, y) {
  return Number(x - y);
}
// SIGN
// ----
/**
 * Get the absolute of a bigint.
 * @param x a bigint
 * @returns |x|
 */ export function abs(x) {
  return x < 0n ? -x : x;
}
/**
 * Get the sign of a bigint.
 * @param x a bigint
 * @returns x>0: 1n, x<0: -1n, x=0: 0n
 */ export function sign(x) {
  return x < 0n ? -1n : x > 0n ? 1n : 0n;
}
// ROUNDED DIVISION
// ----------------
/**
 * Perform floor-divison of two bigints (\\).
 * @param x dividend
 * @param y divisor
 * @returns ⌊x/y⌋
 */ export function floorDiv(x, y) {
  if (y < 0n) {
    x = -x;
    y = -y;
  }
  return x >= 0n ? x / y : (x - y + 1n) / y;
}
// - https://python-reference.readthedocs.io/en/latest/docs/operators/floor_division.html
/**
 * Perform ceiling-divison of two bigints.
 * @param x dividend
 * @param y divisor
 * @returns ⌈x/y⌉
 */ export function ceilDiv(x, y) {
  if (y < 0n) {
    x = -x;
    y = -y;
  }
  return x >= 0n ? (x + y - 1n) / y : x / y;
}
/**
 * Perform rounded-divison of two bigints.
 * @param x divisor
 * @param y dividend
 * @returns [x/y]
 */ export function roundDiv(x, y) {
  if (y < 0n) {
    x = -x;
    y = -y;
  }
  return x >= 0n ? (x + y / 2n) / y : (x - y / 2n) / y;
}
// MODULO
// ------
/**
 * Find the remainder of x/y with sign of x (truncated division).
 * @param x dividend
 * @param y divisor
 * @returns trunc(x % y)
 */ export function rem(x, y) {
  return x % y;
}
// - https://en.wikipedia.org/wiki/Modulo_operation
/**
 * Find the remainder of x/y with sign of y (floored division).
 * @param x dividend
 * @param y divisor
 * @returns floor(x % y)
 */ export function mod(x, y) {
  return x - y * floorDiv(x, y);
}
// - https://en.wikipedia.org/wiki/Modulo_operation
/**
 * Find the remainder of x/y with +ve sign (euclidean division).
 * @param x dividend
 * @param y divisor
 * @returns x/y>0: floor(x % y), x/y<0: ceil(x % y)
 */ export function modp(x, y) {
  return x - abs(y) * floorDiv(x, abs(y));
}
// - https://en.wikipedia.org/wiki/Modulo_operation
// RANGE CONTROL
// -------------
/**
 * Constrain a bigint within a minimum and a maximum value.
 * @param x a bigint
 * @param minv minimum value
 * @param maxv maximum value
 * @returns x<min: min, x>max: max, x
 */ export function constrain(x, minv, maxv) {
  return min(max(x, minv), maxv);
}
export { constrain as clamp };
// - https://processing.org/reference/constrain_.html
// - https://www.npmjs.com/package/clamp
// - https://en.cppreference.com/w/cpp/algorithm/clamp
// - https://dlang.org/library/std/algorithm/comparison/clamp.html
// - https://www.rdocumentation.org/packages/raster/versions/3.0-12/topics/clamp
// - https://docs.microsoft.com/en-us/dotnet/api/system.math.clamp?view=netcore-3.1
// - https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-clamp
// - https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/clamp.xhtml
// - https://docs.unity3d.com/ScriptReference/Mathf.Clamp.html
// - https://en.wikipedia.org/wiki/Clamping_(graphics)
/**
 * Re-map a bigint from one range to another.
 * @param x a bigint
 * @param r lower bound of current range
 * @param R upper bound of current range
 * @param t lower bound of target range
 * @param T upper bound of target range
 * @returns ∈ [ymin, ymax]
 */ export function remap(x, r, R, t, T) {
  return t + (x - r) * (T - t) / (R - r);
}
export { remap as map };
// - https://processing.org/reference/map_.html
/**
 * Linearly interpolate a bigint between two bigints.
 * @param x start bigint
 * @param y stop bigint
 * @param t interpolant ∈ [0, 1]
 * @returns ∈ [x, y]
 */ export function lerp(x, y, t) {
  return x + BigInt(Math.floor(t * Number(y - x)));
}
// - https://processing.org/reference/lerp_.html
// - https://docs.unity3d.com/ScriptReference/Vector3.Lerp.html
// - https://stackoverflow.com/questions/53970655/how-to-convert-bigint-to-number-in-javascript
// POWER / LOGARITHM
// -----------------
/**
 * Check if bigint is a power-of-2.
 * @param x a bigint
 * @returns 2ⁱ = x? | i = +ve integer
 */ export function isPow2(x) {
  return /^10*$/.test(x.toString(2));
}
/**
 * Check if bigint is a power-of-10.
 * @param x a bigint
 * @returns 10ⁱ = x? | i = +ve integer
 */ export function isPow10(x) {
  return /^10*$/.test(x.toString());
}
/**
 * Find largest power-of-2 less than or equal to given bigint.
 * @param x a bigint
 * @returns 2ⁱ | 2ⁱ ≤ x and 2ⁱ > x/2
 */ export function prevPow2(x) {
  if (x <= 1n) return 0n;
  const n = x.toString(2).length;
  return BigInt("0b1" + "0".repeat(n - 1));
}
/**
 * Find largest power-of-10 less than or equal to given bigint.
 * @param x a bigint
 * @returns 10ⁱ | 10ⁱ ≤ x and 10ⁱ > x/10
 */ export function prevPow10(x) {
  if (x <= 1n) return 0n;
  const n = x.toString(10).length;
  return BigInt("1" + "0".repeat(n - 1));
}
/**
 * Find smallest power-of-2 greater than or equal to given bigint.
 * @param x a bigint
 * @returns 2ⁱ | 2ⁱ ≥ x and 2ⁱ < 2x
 */ export function nextPow2(x) {
  if (x <= 0n) return 1n;
  const n = (x - 1n).toString(2).length;
  return BigInt("0b1" + "0".repeat(n));
}
/**
 * Find smallest power-of-10 greater than or equal to given bigint.
 * @param x a bigint
 * @returns 10ⁱ | 10ⁱ ≥ x and 10ⁱ < 10x
 */ export function nextPow10(x) {
  if (x <= 0n) return 1n;
  const n = (x - 1n).toString(10).length;
  return BigInt("1" + "0".repeat(n));
}
/**
 * Find the base-2 logarithm of a bigint.
 * @param x a bigint
 * @returns log₂(x)
 */ export function log2(x) {
  const n = x.toString(2).length - 1;
  return x <= 0n ? 0n : BigInt(n);
}
/**
 * Find the base-10 logarithm of a bigint.
 * @param x a bigint
 * @returns log₁₀(x)
 */ export function log10(x) {
  const n = x.toString().length - 1;
  return x <= 0n ? 0n : BigInt(n);
}
// TODO: isPow() based on accelerated search
// TODO: prevPow() based on accelerated search
// TODO: nextPow() based on accelerated search
// TODO: log() based on accelerated search
// ROOT
// ----
/**
 * Find the square root of a bigint.
 * @param x a bigint
 * @returns √x
 */ export function sqrt(x) {
  if (x === 0n) return 0n;
  return x > 0n ? sqrtPos(x) : null;
}
function sqrtPos(x) {
  let a = 1n << log2(x) / 2n + 1n; // initial guess
  let b = 1n + a;
  while(a < b){
    b = a;
    a = (b + x / b) / 2n;
  }
  return b;
}
/**
 * Find the cube root of a bigint.
 * @param x a bigint
 * @returns ³√x
 */ export function cbrt(x) {
  return root(x, 3n);
}
/**
 * Find the nth root of a bigint.
 * @param x a bigint
 * @param n nth root (1n)
 * @returns ⁿ√x
 */ export function root(x, n = 1n) {
  if (x === 0n) return 0n;
  else if (x > 0n) return rootPos(x, n);
  return n % 2n !== 0n ? -rootPos(-x, n) : null;
}
function rootPos(x, n) {
  let a = 1n << log2(x) / n + 1n; // initial guess
  let b = 1n + a;
  const m = n - 1n;
  if (a === 2n) return 1n;
  while(a < b){
    b = a;
    a = (m * b + x / b ** m) / n;
  }
  return b;
}
// DIVISORS
// --------
/**
 * List all divisors of a bigint, except itself.
 * @param x a bigint
 * @returns proper divisors (factors)
 */ export function properDivisors(x) {
  x = abs(x);
  const a = [];
  for(let i = 1n; i < x; i++)if (x % i === 0n) a.push(i);
  return a;
}
export { properDivisors as aliquotParts };
// - https://mathworld.wolfram.com/ProperDivisor.html
// - https://en.wikipedia.org/wiki/Divisor#Further_notions_and_facts
/**
 * Sum all proper divisors of a bigint.
 * @param x a bigint
 * @returns Σdᵢ | dᵢ is a divisor of x and ≠x
 */ export function aliquotSum(x) {
  x = abs(x);
  let a = 0n;
  for(let i = 1n; i < x; i++)if (x % i === 0n) a += i;
  return a;
}
/**
 * Find the least prime number which divides a bigint.
 * @param x a bigint
 * @returns least prime factor
 */ export function minPrimeFactor(x) {
  x = abs(x);
  // 1. LPF of 2, 3 is the number itself.
  if (x <= 1n) return 0n;
  if (x <= 3n) return x;
  // 2. LPF for multiples of 2, 3.
  if (x % 2n === 0n) return 2n;
  if (x % 3n === 0n) return 3n;
  // 3. LPF can be 6k-1 or 6k+1.
  for(let i = 6n, I = sqrt(x) + 1n; i <= I; i += 6n){
    if (x % (i - 1n) === 0n) return i - 1n;
    if (x % (i + 1n) === 0n) return i + 1n;
  }
  return x;
}
export { minPrimeFactor as leastPrimeFactor };
// - https://mathworld.wolfram.com/LeastPrimeFactor.html
/**
 * Find the greatest prime number which divides a bigint.
 * @param x a bigint
 * @returns greatest prime factor
 */ export function maxPrimeFactor(x) {
  x = abs(x);
  let a = 0n;
  // 1. GPF of 2, 3 is the number itself.
  if (x <= 1n) return 0n;
  if (x <= 3n) return x;
  // 2. Remove factors 2, 3.
  for(; x % 2n === 0n; a = 2n)x /= 2n;
  for(; x % 3n === 0n; a = 3n)x /= 3n;
  // 3. Remove factors 6k-1, 6k+1.
  for(let i = 6n, I = sqrt(x) + 1n; x > 1n && i <= I; i += 6n){
    for(; x % (i - 1n) == 0n; a = i - 1n)x /= i - 1n;
    for(; x % (i + 1n) == 0n; a = i + 1n)x /= i + 1n;
  }
  if (x <= 1n) return a;
  return x;
}
export { maxPrimeFactor as greatestPrimeFactor };
// - https://mathworld.wolfram.com/GreatestPrimeFactor.html
// - https://www.geeksforgeeks.org/find-largest-prime-factor-number/
/**
 * Find the prime factors of a bigint.
 * @param x a bigint
 * @returns [f₀, f₁, ...] | fᵢ divides x and is prime
 */ export function primeFactors(x) {
  x = abs(x);
  const a = [];
  if (x <= 1n) return [];
  if (x <= 3n) return [
    x
  ];
  // 2. Try factors 2, 3.
  x = pushPrimeFactorTo$(a, x, 2n);
  x = pushPrimeFactorTo$(a, x, 3n);
  // 3. Try factors 6k-1, 6k+1.
  for(let i = 6n, I = sqrt(x) + 1n; x > 1n && i <= I; i += 6n){
    x = pushPrimeFactorTo$(a, x, i - 1n);
    x = pushPrimeFactorTo$(a, x, i + 1n);
  }
  if (x > 1n) a.push(x);
  return a;
}
function pushPrimeFactorTo$(a, x, f) {
  if (x % f !== 0n) return x;
  do {
    x /= f;
  }while (x % f === 0n)
  a.push(f);
  return x;
}
// - https://www.geeksforgeeks.org/prime-factors-big-number/
// - https://mathworld.wolfram.com/PrimeFactor.html
/**
 * Find the prime factors and respective exponents of a bigint.
 * @param x a bigint
 * @returns [[f₀, e₀], [f₁, e₁], ...] | fᵢ is a prime factor of x and eᵢ is its exponent
 */ export function primeExponentials(x) {
  x = abs(x);
  const a = [];
  if (x <= 1n) return [];
  if (x <= 3n) return [
    [
      x,
      1n
    ]
  ];
  // 2. Try factors 2, 3.
  x = pushPrimeExponentialTo$(a, x, 2n);
  x = pushPrimeExponentialTo$(a, x, 3n);
  // 3. Try factors 6k-1, 6k+1.
  for(let i = 6n, I = sqrt(x) + 1n; x > 1n && i <= I; i += 6n){
    x = pushPrimeExponentialTo$(a, x, i - 1n);
    x = pushPrimeExponentialTo$(a, x, i + 1n);
  }
  if (x > 1n) a.push([
    x,
    1n
  ]);
  return a;
}
function pushPrimeExponentialTo$(a, x, f) {
  if (x % f !== 0n) return x;
  let e = 0n;
  do {
    x /= f;
    ++e;
  }while (x % f === 0n)
  a.push([
    f,
    e
  ]);
  return x;
}
// - https://www.geeksforgeeks.org/prime-factors-big-number/
// - https://reference.wolfram.com/language/ref/FactorInteger.html
// - https://mathworld.wolfram.com/PrimeFactorization.html
// - https://mathworld.wolfram.com/PrimeFactor.html
/**
 * Check if bigint is prime.
 * @param x a bigint
 * @returns is divisible by 1n and itself only?
 */ export function isPrime(x) {
  return x !== 0n && minPrimeFactor(x) === abs(x);
}
/**
 * Find the greatest common divisor of bigints.
 * @param xs a list of bigints
 * @returns gcd(x₁, x₂, ...)
 */ export function gcd(...xs) {
  let a = xs[0] || 1n;
  for(let i = 1, I = xs.length; i < I; i++)a = gcdPair(a, xs[i]);
  return a;
}
export { gcd as hcf };
// Find the greatest common divisor of a pair of bigints.
function gcdPair(x, y) {
  while(y !== 0n){
    const t = y;
    y = x % y;
    x = t;
  }
  return x;
}
// - https://lemire.me/blog/2013/12/26/fastest-way-to-compute-the-greatest-common-divisor/
// - https://en.wikipedia.org/wiki/Euclidean_algorithm
/**
 * Find the least common multiple of bigints.
 * @param xs a list of bigints
 * @returns lcm(x₁, x₂, ...)
 */ export function lcm(...xs) {
  let a = xs[0] || 1n;
  for(let i = 1, I = xs.length; i < I; i++)a = a * xs[i] / gcdPair(a, xs[i]);
  return a;
}
// - https://en.wikipedia.org/wiki/Least_common_multiple
// ARRANGEMENTS
// ------------
/**
 * Find the factorial of a bigint.
 * @param n a bigint
 * @param k denominator factorial [0]
 * @returns P(n, k); k=0: n!, k>0: n!/k!
 */ export function factorial(n, k = 0n) {
  let a = 1n;
  if (n < 0n) return 0n;
  for(let i = k + 1n; i <= n; i++)a *= i;
  return a;
}
// - https://github.com/alawatthe/MathLib/blob/master/src/Functn/functions/factorial.ts
// - https://en.wikipedia.org/wiki/Permutation
/**
 * Find the number of ways to choose k elements from a set of n elements.
 * @param n elements in source set
 * @param k elements in choose set
 * @returns C(n, k)
 */ export function binomial(n, k) {
  // 1. Generalization to negative integers
  if (k < 0n || k > abs(n)) return 0n;
  if (n < 0n) return (-1n) ** k * binomial(-n, k);
  // 2. Take advantage of symmetry
  k = k > n - k ? n - k : k;
  let a = 1n, b = 1n;
  for(let i = 1n; i <= k; i++, n--){
    a *= n;
    b *= i;
  }
  return a / b;
}
// - https://github.com/alawatthe/MathLib/blob/master/src/Functn/functions/binomial.ts
// - https://en.wikipedia.org/wiki/Binomial_coefficient
/**
 * Find the number of ways to put n objects in m bins (n=sum(kᵢ)).
 * @param ks objects per bin (kᵢ)
 * @returns n!/(k₁!k₂!...) | n=sum(kᵢ)
 */ export function multinomial(...ks) {
  let n = sum(...ks), a = 1n, b = 1n;
  for(let i = 0, j = 0n, I = ks.length; i < I;){
    if (j <= 0n) j = ks[i++];
    else {
      a *= n--;
      b *= j--;
    }
  }
  return a / b;
}
// - https://en.wikipedia.org/wiki/Multinomial_distribution
// GEOMETRY
// --------
/**
 * Find the length of hypotenuse.
 * @param xs lengths of perpendicular sides (x, y, z, ...)
 * @returns √(x² + y² + z²)
 */ export function hypot(...xs) {
  let a = 0n;
  for (const x of xs)a += x * x;
  return sqrt(a);
}
// STATISTICS
// ----------
/**
 * Find the sum of bigints (Σ).
 * @param xs bigints
 * @returns Σxᵢ
 */ export function sum(...xs) {
  let a = 0n;
  for (const x of xs)a += x;
  return a;
}
/**
 * Find the product of bigints (∏).
 * @param xs bigints
 * @returns ∏xᵢ
 */ export function product(...xs) {
  let a = 1n;
  for (const x of xs)a *= x;
  return a;
}
/**
 * Find the value separating the higher and lower halves of bigints.
 * @param xs a list of bigints
 * @returns xₘ | sort(xs) = [..., xₘ, ...]
 */ export function median(...xs) {
  if (xs.length === 0) return 0n;
  xs.sort(compare);
  const i = xs.length >> 1;
  if ((xs.length & 1) === 1) return xs[i];
  return (xs[i - 1] + xs[i]) / 2n;
}
// - https://stackoverflow.com/questions/45309447/calculating-median-javascript
// - https://en.wikipedia.org/wiki/Median
/**
 * Find the values that appear most often.
 * @param xs a list of bigints
 * @returns [xₘ₁, xₘ₂, ...] | count(xₘᵢ) ≥ count(xᵢ) ∀ xᵢ ∈ xs
 */ export function modes(...xs) {
  xs.sort(compare);
  const r = maxRepeat(xs);
  return getRepeats(xs, r);
}
// - https://en.wikipedia.org/wiki/Mode_(statistics)
// Get the maximum number of times any bigint has repeated in a sorted array.
function maxRepeat(xs) {
  let count = Math.min(xs.length, 1), max = count;
  for(let i = 1, I = xs.length; i < I; i++){
    if (xs[i - 1] === xs[i]) count++;
    else {
      max = Math.max(max, count);
      count = 1;
    }
  }
  return Math.max(max, count);
}
// Get the numbers which have been repeated atleast given number of times.
function getRepeats(xs, r) {
  const a = [];
  r--;
  for(let i = 0, I = xs.length - r; i < I; i++)if (xs[i] === xs[i + r]) a.push(xs[i += r]);
  return a;
}
/**
 * Find the smallest bigint.
 * @param xs bigints
 * @returns min(xs)
 */ export function min(...xs) {
  if (xs.length === 0) return 0n;
  let a = xs[0];
  for (const x of xs)a = x < a ? x : a;
  return a;
}
/**
 * Find the largest bigint.
 * @param xs bigints
 * @returns max(xs)
 */ export function max(...xs) {
  if (xs.length === 0) return 0n;
  let a = xs[0];
  for (const x of xs)a = x > a ? x : a;
  return a;
}
/**
 * Find the minimum and maximum bigint.
 * @param xs bigints
 * @returns [min, max]
 */ export function range(...xs) {
  if (xs.length === 0) return [
    0n,
    0n
  ];
  let a = xs[0], b = a;
  for (const x of xs){
    a = x < a ? x : a;
    b = x > b ? x : b;
  }
  return [
    a,
    b
  ];
}
/**
 * Find the mean of squared deviation of bigints from its mean.
 * @param xs a list of bigints
 * @returns σ² = E[(xs - µ)²] | µ = mean(xs)
 */ export function variance(...xs) {
  if (xs.length === 0) return 0n;
  const m = arithmeticMean(...xs);
  let a = 0n;
  for (const x of xs)a += (x - m) ** 2n;
  return a / BigInt(xs.length);
}
// - https://en.wikipedia.org/wiki/Variance
// MEAN (STATISTICS)
// -----------------
/**
 * Find the arithmetic mean of bigints (µ).
 * @param xs bigints
 * @returns µ = (Σxᵢ)/n | n = size(xs)
 */ export function arithmeticMean(...xs) {
  const n = BigInt(xs.length);
  return sum(...xs) / n;
}
export { arithmeticMean as mean };
/**
 * Find the geometric mean of bigints.
 * @param xs bigints
 * @returns ⁿ√(∏xᵢ) | n = size(xs)
 */ export function geometricMean(...xs) {
  const n = BigInt(xs.length);
  return root(product(...xs), n);
}
/**
 * Find the harmonic mean of bigints.
 * @param xs bigints
 * @returns n/Σ(1/xᵢ) | n = size(xs)
 */ export function harmonicMean(...xs) {
  const n = BigInt(xs.length);
  const p = product(...xs);
  let q = 0n;
  for (const x of xs)q += p / x;
  return n * p / q;
}
/**
 * Find the quadriatic mean of bigints.
 * @param xs bigints
 * @returns √(Σxᵢ²)/n | n = size(xs)
 */ export function quadriaticMean(...xs) {
  const n = BigInt(xs.length);
  let a = 0n;
  for (const x of xs)a += x * x;
  return sqrt(a / n);
}
export { quadriaticMean as rootMeanSquare };
/**
 * Find the cubic mean of bigints.
 * @param xs bigints
 * @returns ³√(Σxᵢ³)/n | n = size(xs)
 */ export function cubicMean(...xs) {
  const n = BigInt(xs.length);
  let a = 0n;
  for (const x of xs)a += x ** 3n;
  return cbrt(a / n);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9leHRyYS1iaWdpbnQvZXh0cmEtYmlnaW50L2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIE1FVEhPRFNcbi8vID09PT09PT1cblxuLy8gQUJPVVRcbi8vIC0tLS0tXG5cbi8qKlxuICogQ2hlY2sgaWYgdmFsdWUgaXMgYSBiaWdpbnQuXG4gKiBAcGFyYW0geCBhIHZhbHVlXG4gKiBAcmV0dXJucyBpcyBiaWdpbnQ/XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpcyh4OiB1bmtub3duKTogeCBpcyBiaWdpbnQge1xuICByZXR1cm4gdHlwZW9mIHg9PT1cImJpZ2ludFwiO1xufVxuXG5cblxuXG4vLyBDT01QQVJFXG4vLyAtLS0tLS0tXG5cbi8qKlxuICogQ29tcGFyZSB0d28gYmlnaW50cy5cbiAqIEBwYXJhbSB4IGEgYmlnaW50XG4gKiBAcGFyYW0geSBhbm90aGVyIGJpZ2ludFxuICogQHJldHVybnMgeDx5OiAtdmUsIHg9eTogMCwgeD55OiArdmVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbXBhcmUoeDogYmlnaW50LCB5OiBiaWdpbnQpOiBudW1iZXIge1xuICByZXR1cm4gTnVtYmVyKHgteSk7XG59XG5cblxuXG5cbi8vIFNJR05cbi8vIC0tLS1cblxuLyoqXG4gKiBHZXQgdGhlIGFic29sdXRlIG9mIGEgYmlnaW50LlxuICogQHBhcmFtIHggYSBiaWdpbnRcbiAqIEByZXR1cm5zIHx4fFxuICovXG5leHBvcnQgZnVuY3Rpb24gYWJzKHg6IGJpZ2ludCk6IGJpZ2ludCB7XG4gIHJldHVybiB4PDBuPyAteCA6IHg7XG59XG5cblxuLyoqXG4gKiBHZXQgdGhlIHNpZ24gb2YgYSBiaWdpbnQuXG4gKiBAcGFyYW0geCBhIGJpZ2ludFxuICogQHJldHVybnMgeD4wOiAxbiwgeDwwOiAtMW4sIHg9MDogMG5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNpZ24oeDogYmlnaW50KTogYmlnaW50IHtcbiAgcmV0dXJuIHg8MG4/IC0xbiA6ICh4PjBuPyAxbiA6IDBuKTtcbn1cblxuXG5cblxuLy8gUk9VTkRFRCBESVZJU0lPTlxuLy8gLS0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIFBlcmZvcm0gZmxvb3ItZGl2aXNvbiBvZiB0d28gYmlnaW50cyAoXFxcXCkuXG4gKiBAcGFyYW0geCBkaXZpZGVuZFxuICogQHBhcmFtIHkgZGl2aXNvclxuICogQHJldHVybnMg4oyKeC954oyLXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmbG9vckRpdih4OiBiaWdpbnQsIHk6IGJpZ2ludCk6IGJpZ2ludCB7XG4gIGlmICh5PDBuKSB7IHggPSAteDsgeSA9IC15OyB9XG4gIHJldHVybiB4Pj0wbj8geC95IDogKHgteSsxbikveTtcbn1cbi8vIC0gaHR0cHM6Ly9weXRob24tcmVmZXJlbmNlLnJlYWR0aGVkb2NzLmlvL2VuL2xhdGVzdC9kb2NzL29wZXJhdG9ycy9mbG9vcl9kaXZpc2lvbi5odG1sXG5cblxuLyoqXG4gKiBQZXJmb3JtIGNlaWxpbmctZGl2aXNvbiBvZiB0d28gYmlnaW50cy5cbiAqIEBwYXJhbSB4IGRpdmlkZW5kXG4gKiBAcGFyYW0geSBkaXZpc29yXG4gKiBAcmV0dXJucyDijIh4L3nijIlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNlaWxEaXYoeDogYmlnaW50LCB5OiBiaWdpbnQpOiBiaWdpbnQge1xuICBpZiAoeTwwbikgeyB4ID0gLXg7IHkgPSAteTsgfVxuICByZXR1cm4geD49MG4/ICh4K3ktMW4pL3kgOiB4L3k7XG59XG5cblxuLyoqXG4gKiBQZXJmb3JtIHJvdW5kZWQtZGl2aXNvbiBvZiB0d28gYmlnaW50cy5cbiAqIEBwYXJhbSB4IGRpdmlzb3JcbiAqIEBwYXJhbSB5IGRpdmlkZW5kXG4gKiBAcmV0dXJucyBbeC95XVxuICovXG5leHBvcnQgZnVuY3Rpb24gcm91bmREaXYoeDogYmlnaW50LCB5OiBiaWdpbnQpOiBiaWdpbnQge1xuICBpZiAoeTwwbikgeyB4ID0gLXg7IHkgPSAteTsgfVxuICByZXR1cm4geD49MG4/ICh4K3kvMm4pL3kgOiAoeC15LzJuKS95O1xufVxuXG5cblxuXG4vLyBNT0RVTE9cbi8vIC0tLS0tLVxuXG4vKipcbiAqIEZpbmQgdGhlIHJlbWFpbmRlciBvZiB4L3kgd2l0aCBzaWduIG9mIHggKHRydW5jYXRlZCBkaXZpc2lvbikuXG4gKiBAcGFyYW0geCBkaXZpZGVuZFxuICogQHBhcmFtIHkgZGl2aXNvclxuICogQHJldHVybnMgdHJ1bmMoeCAlIHkpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZW0oeDogYmlnaW50LCB5OiBiaWdpbnQpOiBiaWdpbnQge1xuICByZXR1cm4geCAlIHk7XG59XG4vLyAtIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL01vZHVsb19vcGVyYXRpb25cblxuXG4vKipcbiAqIEZpbmQgdGhlIHJlbWFpbmRlciBvZiB4L3kgd2l0aCBzaWduIG9mIHkgKGZsb29yZWQgZGl2aXNpb24pLlxuICogQHBhcmFtIHggZGl2aWRlbmRcbiAqIEBwYXJhbSB5IGRpdmlzb3JcbiAqIEByZXR1cm5zIGZsb29yKHggJSB5KVxuICovXG5leHBvcnQgZnVuY3Rpb24gbW9kKHg6IGJpZ2ludCwgeTogYmlnaW50KTogYmlnaW50IHtcbiAgcmV0dXJuIHggLSB5KmZsb29yRGl2KHgsIHkpO1xufVxuLy8gLSBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Nb2R1bG9fb3BlcmF0aW9uXG5cblxuLyoqXG4gKiBGaW5kIHRoZSByZW1haW5kZXIgb2YgeC95IHdpdGggK3ZlIHNpZ24gKGV1Y2xpZGVhbiBkaXZpc2lvbikuXG4gKiBAcGFyYW0geCBkaXZpZGVuZFxuICogQHBhcmFtIHkgZGl2aXNvclxuICogQHJldHVybnMgeC95PjA6IGZsb29yKHggJSB5KSwgeC95PDA6IGNlaWwoeCAlIHkpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtb2RwKHg6IGJpZ2ludCwgeTogYmlnaW50KTogYmlnaW50IHtcbiAgcmV0dXJuIHggLSBhYnMoeSkqZmxvb3JEaXYoeCwgYWJzKHkpKTtcbn1cbi8vIC0gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTW9kdWxvX29wZXJhdGlvblxuXG5cblxuXG4vLyBSQU5HRSBDT05UUk9MXG4vLyAtLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogQ29uc3RyYWluIGEgYmlnaW50IHdpdGhpbiBhIG1pbmltdW0gYW5kIGEgbWF4aW11bSB2YWx1ZS5cbiAqIEBwYXJhbSB4IGEgYmlnaW50XG4gKiBAcGFyYW0gbWludiBtaW5pbXVtIHZhbHVlXG4gKiBAcGFyYW0gbWF4diBtYXhpbXVtIHZhbHVlXG4gKiBAcmV0dXJucyB4PG1pbjogbWluLCB4Pm1heDogbWF4LCB4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb25zdHJhaW4oeDogYmlnaW50LCBtaW52OiBiaWdpbnQsIG1heHY6IGJpZ2ludCk6IGJpZ2ludCB7XG4gIHJldHVybiBtaW4obWF4KHgsIG1pbnYpLCBtYXh2KTtcbn1cbmV4cG9ydCB7Y29uc3RyYWluIGFzIGNsYW1wfTtcbi8vIC0gaHR0cHM6Ly9wcm9jZXNzaW5nLm9yZy9yZWZlcmVuY2UvY29uc3RyYWluXy5odG1sXG4vLyAtIGh0dHBzOi8vd3d3Lm5wbWpzLmNvbS9wYWNrYWdlL2NsYW1wXG4vLyAtIGh0dHBzOi8vZW4uY3BwcmVmZXJlbmNlLmNvbS93L2NwcC9hbGdvcml0aG0vY2xhbXBcbi8vIC0gaHR0cHM6Ly9kbGFuZy5vcmcvbGlicmFyeS9zdGQvYWxnb3JpdGhtL2NvbXBhcmlzb24vY2xhbXAuaHRtbFxuLy8gLSBodHRwczovL3d3dy5yZG9jdW1lbnRhdGlvbi5vcmcvcGFja2FnZXMvcmFzdGVyL3ZlcnNpb25zLzMuMC0xMi90b3BpY3MvY2xhbXBcbi8vIC0gaHR0cHM6Ly9kb2NzLm1pY3Jvc29mdC5jb20vZW4tdXMvZG90bmV0L2FwaS9zeXN0ZW0ubWF0aC5jbGFtcD92aWV3PW5ldGNvcmUtMy4xXG4vLyAtIGh0dHBzOi8vZG9jcy5taWNyb3NvZnQuY29tL2VuLXVzL3dpbmRvd3Mvd2luMzIvZGlyZWN0M2RobHNsL2R4LWdyYXBoaWNzLWhsc2wtY2xhbXBcbi8vIC0gaHR0cHM6Ly93d3cua2hyb25vcy5vcmcvcmVnaXN0cnkvT3BlbkdMLVJlZnBhZ2VzL2dsNC9odG1sL2NsYW1wLnhodG1sXG4vLyAtIGh0dHBzOi8vZG9jcy51bml0eTNkLmNvbS9TY3JpcHRSZWZlcmVuY2UvTWF0aGYuQ2xhbXAuaHRtbFxuLy8gLSBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9DbGFtcGluZ18oZ3JhcGhpY3MpXG5cblxuLyoqXG4gKiBSZS1tYXAgYSBiaWdpbnQgZnJvbSBvbmUgcmFuZ2UgdG8gYW5vdGhlci5cbiAqIEBwYXJhbSB4IGEgYmlnaW50XG4gKiBAcGFyYW0gciBsb3dlciBib3VuZCBvZiBjdXJyZW50IHJhbmdlXG4gKiBAcGFyYW0gUiB1cHBlciBib3VuZCBvZiBjdXJyZW50IHJhbmdlXG4gKiBAcGFyYW0gdCBsb3dlciBib3VuZCBvZiB0YXJnZXQgcmFuZ2VcbiAqIEBwYXJhbSBUIHVwcGVyIGJvdW5kIG9mIHRhcmdldCByYW5nZVxuICogQHJldHVybnMg4oiIIFt5bWluLCB5bWF4XVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVtYXAoeDogYmlnaW50LCByOiBiaWdpbnQsIFI6IGJpZ2ludCwgdDogYmlnaW50LCBUOiBiaWdpbnQpOiBiaWdpbnQge1xuICByZXR1cm4gdCArICh4IC0gcikqKFQgLSB0KS8oUiAtIHIpO1xufVxuZXhwb3J0IHtyZW1hcCBhcyBtYXB9O1xuLy8gLSBodHRwczovL3Byb2Nlc3Npbmcub3JnL3JlZmVyZW5jZS9tYXBfLmh0bWxcblxuXG4vKipcbiAqIExpbmVhcmx5IGludGVycG9sYXRlIGEgYmlnaW50IGJldHdlZW4gdHdvIGJpZ2ludHMuXG4gKiBAcGFyYW0geCBzdGFydCBiaWdpbnRcbiAqIEBwYXJhbSB5IHN0b3AgYmlnaW50XG4gKiBAcGFyYW0gdCBpbnRlcnBvbGFudCDiiIggWzAsIDFdXG4gKiBAcmV0dXJucyDiiIggW3gsIHldXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsZXJwKHg6IGJpZ2ludCwgeTogYmlnaW50LCB0OiBudW1iZXIpOiBiaWdpbnQge1xuICByZXR1cm4geCArIEJpZ0ludChNYXRoLmZsb29yKHQqTnVtYmVyKHkgLSB4KSkpO1xufVxuLy8gLSBodHRwczovL3Byb2Nlc3Npbmcub3JnL3JlZmVyZW5jZS9sZXJwXy5odG1sXG4vLyAtIGh0dHBzOi8vZG9jcy51bml0eTNkLmNvbS9TY3JpcHRSZWZlcmVuY2UvVmVjdG9yMy5MZXJwLmh0bWxcbi8vIC0gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNTM5NzA2NTUvaG93LXRvLWNvbnZlcnQtYmlnaW50LXRvLW51bWJlci1pbi1qYXZhc2NyaXB0XG5cblxuXG5cbi8vIFBPV0VSIC8gTE9HQVJJVEhNXG4vLyAtLS0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIENoZWNrIGlmIGJpZ2ludCBpcyBhIHBvd2VyLW9mLTIuXG4gKiBAcGFyYW0geCBhIGJpZ2ludFxuICogQHJldHVybnMgMuKBsSA9IHg/IHwgaSA9ICt2ZSBpbnRlZ2VyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1BvdzIoeDogYmlnaW50KTogYm9vbGVhbiB7XG4gIHJldHVybiAvXjEwKiQvLnRlc3QoeC50b1N0cmluZygyKSk7XG59XG5cblxuLyoqXG4gKiBDaGVjayBpZiBiaWdpbnQgaXMgYSBwb3dlci1vZi0xMC5cbiAqIEBwYXJhbSB4IGEgYmlnaW50XG4gKiBAcmV0dXJucyAxMOKBsSA9IHg/IHwgaSA9ICt2ZSBpbnRlZ2VyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1BvdzEwKHg6IGJpZ2ludCk6IGJvb2xlYW4ge1xuICByZXR1cm4gL14xMCokLy50ZXN0KHgudG9TdHJpbmcoKSk7XG59XG5cblxuLyoqXG4gKiBGaW5kIGxhcmdlc3QgcG93ZXItb2YtMiBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gZ2l2ZW4gYmlnaW50LlxuICogQHBhcmFtIHggYSBiaWdpbnRcbiAqIEByZXR1cm5zIDLigbEgfCAy4oGxIOKJpCB4IGFuZCAy4oGxID4geC8yXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcmV2UG93Mih4OiBiaWdpbnQpOiBiaWdpbnQge1xuICBpZiAoeDw9MW4pIHJldHVybiAwbjtcbiAgY29uc3QgbiA9IHgudG9TdHJpbmcoMikubGVuZ3RoO1xuICByZXR1cm4gQmlnSW50KFwiMGIxXCIgKyBcIjBcIi5yZXBlYXQobi0xKSk7XG59XG5cblxuLyoqXG4gKiBGaW5kIGxhcmdlc3QgcG93ZXItb2YtMTAgbGVzcyB0aGFuIG9yIGVxdWFsIHRvIGdpdmVuIGJpZ2ludC5cbiAqIEBwYXJhbSB4IGEgYmlnaW50XG4gKiBAcmV0dXJucyAxMOKBsSB8IDEw4oGxIOKJpCB4IGFuZCAxMOKBsSA+IHgvMTBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByZXZQb3cxMCh4OiBiaWdpbnQpOiBiaWdpbnQge1xuICBpZiAoeDw9MW4pIHJldHVybiAwbjtcbiAgY29uc3QgbiA9IHgudG9TdHJpbmcoMTApLmxlbmd0aDtcbiAgcmV0dXJuIEJpZ0ludChcIjFcIiArIFwiMFwiLnJlcGVhdChuLTEpKTtcbn1cblxuXG4vKipcbiAqIEZpbmQgc21hbGxlc3QgcG93ZXItb2YtMiBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gZ2l2ZW4gYmlnaW50LlxuICogQHBhcmFtIHggYSBiaWdpbnRcbiAqIEByZXR1cm5zIDLigbEgfCAy4oGxIOKJpSB4IGFuZCAy4oGxIDwgMnhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG5leHRQb3cyKHg6IGJpZ2ludCk6IGJpZ2ludCB7XG4gIGlmICh4PD0wbikgcmV0dXJuIDFuO1xuICBjb25zdCBuID0gKHgtMW4pLnRvU3RyaW5nKDIpLmxlbmd0aDtcbiAgcmV0dXJuIEJpZ0ludChcIjBiMVwiICsgXCIwXCIucmVwZWF0KG4pKTtcbn1cblxuXG4vKipcbiAqIEZpbmQgc21hbGxlc3QgcG93ZXItb2YtMTAgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIGdpdmVuIGJpZ2ludC5cbiAqIEBwYXJhbSB4IGEgYmlnaW50XG4gKiBAcmV0dXJucyAxMOKBsSB8IDEw4oGxIOKJpSB4IGFuZCAxMOKBsSA8IDEweFxuICovXG5leHBvcnQgZnVuY3Rpb24gbmV4dFBvdzEwKHg6IGJpZ2ludCk6IGJpZ2ludCB7XG4gIGlmICh4PD0wbikgcmV0dXJuIDFuO1xuICBjb25zdCBuID0gKHgtMW4pLnRvU3RyaW5nKDEwKS5sZW5ndGg7XG4gIHJldHVybiBCaWdJbnQoXCIxXCIgKyBcIjBcIi5yZXBlYXQobikpO1xufVxuXG5cbi8qKlxuICogRmluZCB0aGUgYmFzZS0yIGxvZ2FyaXRobSBvZiBhIGJpZ2ludC5cbiAqIEBwYXJhbSB4IGEgYmlnaW50XG4gKiBAcmV0dXJucyBsb2figoIoeClcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxvZzIoeDogYmlnaW50KTogYmlnaW50IHtcbiAgY29uc3QgbiA9IHgudG9TdHJpbmcoMikubGVuZ3RoIC0gMTtcbiAgcmV0dXJuIHg8PTBuPyAwbiA6IEJpZ0ludChuKTtcbn1cblxuXG4vKipcbiAqIEZpbmQgdGhlIGJhc2UtMTAgbG9nYXJpdGhtIG9mIGEgYmlnaW50LlxuICogQHBhcmFtIHggYSBiaWdpbnRcbiAqIEByZXR1cm5zIGxvZ+KCgeKCgCh4KVxuICovXG5leHBvcnQgZnVuY3Rpb24gbG9nMTAoeDogYmlnaW50KTogYmlnaW50IHtcbiAgY29uc3QgbiA9IHgudG9TdHJpbmcoKS5sZW5ndGggLSAxO1xuICByZXR1cm4geDw9MG4/IDBuIDogQmlnSW50KG4pO1xufVxuXG5cbi8vIFRPRE86IGlzUG93KCkgYmFzZWQgb24gYWNjZWxlcmF0ZWQgc2VhcmNoXG4vLyBUT0RPOiBwcmV2UG93KCkgYmFzZWQgb24gYWNjZWxlcmF0ZWQgc2VhcmNoXG4vLyBUT0RPOiBuZXh0UG93KCkgYmFzZWQgb24gYWNjZWxlcmF0ZWQgc2VhcmNoXG4vLyBUT0RPOiBsb2coKSBiYXNlZCBvbiBhY2NlbGVyYXRlZCBzZWFyY2hcblxuXG5cblxuLy8gUk9PVFxuLy8gLS0tLVxuXG4vKipcbiAqIEZpbmQgdGhlIHNxdWFyZSByb290IG9mIGEgYmlnaW50LlxuICogQHBhcmFtIHggYSBiaWdpbnRcbiAqIEByZXR1cm5zIOKImnhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNxcnQoeDogYmlnaW50KTogYmlnaW50IHwgbnVsbCB7XG4gIGlmICh4PT09MG4pIHJldHVybiAwbjtcbiAgcmV0dXJuIHg+MG4/IHNxcnRQb3MoeCkgOiBudWxsO1xufVxuXG5mdW5jdGlvbiBzcXJ0UG9zKHg6IGJpZ2ludCk6IGJpZ2ludCB7XG4gIGxldCBhID0gMW4gPDwgKGxvZzIoeCkvMm4gKyAxbik7ICAvLyBpbml0aWFsIGd1ZXNzXG4gIGxldCBiID0gMW4gKyBhO1xuICB3aGlsZSAoYTxiKSB7XG4gICAgYiA9IGE7XG4gICAgYSA9IChiICsgeC9iKS8ybjtcbiAgfVxuICByZXR1cm4gYjtcbn1cblxuXG4vKipcbiAqIEZpbmQgdGhlIGN1YmUgcm9vdCBvZiBhIGJpZ2ludC5cbiAqIEBwYXJhbSB4IGEgYmlnaW50XG4gKiBAcmV0dXJucyDCs+KImnhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNicnQoeDogYmlnaW50KTogYmlnaW50IHwgbnVsbCB7XG4gIHJldHVybiByb290KHgsIDNuKTtcbn1cblxuXG4vKipcbiAqIEZpbmQgdGhlIG50aCByb290IG9mIGEgYmlnaW50LlxuICogQHBhcmFtIHggYSBiaWdpbnRcbiAqIEBwYXJhbSBuIG50aCByb290ICgxbilcbiAqIEByZXR1cm5zIOKBv+KImnhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJvb3QoeDogYmlnaW50LCBuOiBiaWdpbnQ9MW4pOiBiaWdpbnQgfCBudWxsIHtcbiAgaWYgKHg9PT0wbikgcmV0dXJuIDBuO1xuICBlbHNlIGlmICh4PjBuKSByZXR1cm4gcm9vdFBvcyh4LCBuKTtcbiAgcmV0dXJuIG4gJSAybiE9PTBuPyAgLXJvb3RQb3MoLXgsIG4pIDogbnVsbDtcbn1cblxuZnVuY3Rpb24gcm9vdFBvcyh4OiBiaWdpbnQsIG46IGJpZ2ludCk6IGJpZ2ludCB7XG4gIGxldCBhID0gMW4gPDwgKGxvZzIoeCkvbiArIDFuKTsgIC8vIGluaXRpYWwgZ3Vlc3NcbiAgbGV0IGIgPSAxbiArIGE7IGNvbnN0IG0gPSBuIC0gMW47XG4gIGlmIChhPT09Mm4pIHJldHVybiAxbjtcbiAgd2hpbGUgKGE8Yikge1xuICAgIGIgPSBhO1xuICAgIGEgPSAobSpiICsgeC9iKiptKS9uO1xuICB9XG4gIHJldHVybiBiO1xufVxuXG5cblxuXG4vLyBESVZJU09SU1xuLy8gLS0tLS0tLS1cblxuLyoqXG4gKiBMaXN0IGFsbCBkaXZpc29ycyBvZiBhIGJpZ2ludCwgZXhjZXB0IGl0c2VsZi5cbiAqIEBwYXJhbSB4IGEgYmlnaW50XG4gKiBAcmV0dXJucyBwcm9wZXIgZGl2aXNvcnMgKGZhY3RvcnMpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcm9wZXJEaXZpc29ycyh4OiBiaWdpbnQpOiBiaWdpbnRbXSB7XG4gIHggPSBhYnMoeCk7IGNvbnN0IGEgPSBbXTtcbiAgZm9yIChsZXQgaT0xbjsgaTx4OyBpKyspXG4gICAgaWYgKHggJSBpPT09MG4pIGEucHVzaChpKTtcbiAgcmV0dXJuIGE7XG59XG5leHBvcnQge3Byb3BlckRpdmlzb3JzIGFzIGFsaXF1b3RQYXJ0c307XG4vLyAtIGh0dHBzOi8vbWF0aHdvcmxkLndvbGZyYW0uY29tL1Byb3BlckRpdmlzb3IuaHRtbFxuLy8gLSBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9EaXZpc29yI0Z1cnRoZXJfbm90aW9uc19hbmRfZmFjdHNcblxuXG4vKipcbiAqIFN1bSBhbGwgcHJvcGVyIGRpdmlzb3JzIG9mIGEgYmlnaW50LlxuICogQHBhcmFtIHggYSBiaWdpbnRcbiAqIEByZXR1cm5zIM6jZOG1oiB8IGThtaIgaXMgYSBkaXZpc29yIG9mIHggYW5kIOKJoHhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFsaXF1b3RTdW0oeDogYmlnaW50KTogYmlnaW50IHtcbiAgeCA9IGFicyh4KTsgbGV0IGEgPSAwbjtcbiAgZm9yIChsZXQgaT0xbjsgaTx4OyBpKyspXG4gICAgaWYgKHggJSBpPT09MG4pIGEgKz0gaTtcbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBGaW5kIHRoZSBsZWFzdCBwcmltZSBudW1iZXIgd2hpY2ggZGl2aWRlcyBhIGJpZ2ludC5cbiAqIEBwYXJhbSB4IGEgYmlnaW50XG4gKiBAcmV0dXJucyBsZWFzdCBwcmltZSBmYWN0b3JcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1pblByaW1lRmFjdG9yKHg6IGJpZ2ludCk6IGJpZ2ludCB7XG4gIHggPSBhYnMoeCk7XG4gIC8vIDEuIExQRiBvZiAyLCAzIGlzIHRoZSBudW1iZXIgaXRzZWxmLlxuICBpZiAoeDw9MW4pIHJldHVybiAwbjtcbiAgaWYgKHg8PTNuKSByZXR1cm4geDtcbiAgLy8gMi4gTFBGIGZvciBtdWx0aXBsZXMgb2YgMiwgMy5cbiAgaWYgKHggJSAybj09PTBuKSByZXR1cm4gMm47XG4gIGlmICh4ICUgM249PT0wbikgcmV0dXJuIDNuO1xuICAvLyAzLiBMUEYgY2FuIGJlIDZrLTEgb3IgNmsrMS5cbiAgZm9yIChsZXQgaT02biwgST0oc3FydCh4KSBhcyBiaWdpbnQpKzFuOyBpPD1JOyBpKz02bikge1xuICAgIGlmICh4ICUgKGktMW4pPT09MG4pIHJldHVybiBpLTFuO1xuICAgIGlmICh4ICUgKGkrMW4pPT09MG4pIHJldHVybiBpKzFuO1xuICB9XG4gIHJldHVybiB4O1xufVxuZXhwb3J0IHttaW5QcmltZUZhY3RvciBhcyBsZWFzdFByaW1lRmFjdG9yfTtcbi8vIC0gaHR0cHM6Ly9tYXRod29ybGQud29sZnJhbS5jb20vTGVhc3RQcmltZUZhY3Rvci5odG1sXG5cblxuLyoqXG4gKiBGaW5kIHRoZSBncmVhdGVzdCBwcmltZSBudW1iZXIgd2hpY2ggZGl2aWRlcyBhIGJpZ2ludC5cbiAqIEBwYXJhbSB4IGEgYmlnaW50XG4gKiBAcmV0dXJucyBncmVhdGVzdCBwcmltZSBmYWN0b3JcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1heFByaW1lRmFjdG9yKHg6IGJpZ2ludCk6IGJpZ2ludCB7XG4gIHggPSBhYnMoeCk7IGxldCBhID0gMG47XG4gIC8vIDEuIEdQRiBvZiAyLCAzIGlzIHRoZSBudW1iZXIgaXRzZWxmLlxuICBpZiAoeDw9MW4pIHJldHVybiAwbjtcbiAgaWYgKHg8PTNuKSByZXR1cm4geDtcbiAgLy8gMi4gUmVtb3ZlIGZhY3RvcnMgMiwgMy5cbiAgZm9yICg7IHggJSAybj09PTBuOyBhPTJuKVxuICAgIHggLz0gMm47XG4gIGZvciAoOyB4ICUgM249PT0wbjsgYT0zbilcbiAgICB4IC89IDNuO1xuICAvLyAzLiBSZW1vdmUgZmFjdG9ycyA2ay0xLCA2aysxLlxuICBmb3IgKGxldCBpPTZuLCBJPShzcXJ0KHgpIGFzIGJpZ2ludCkrMW47IHg+MW4gJiYgaTw9STsgaSs9Nm4pIHtcbiAgICBmb3IgKDsgeCAlIChpLTFuKT09MG47IGE9aS0xbilcbiAgICAgIHggLz0gaS0xbjtcbiAgICBmb3IgKDsgeCAlIChpKzFuKT09MG47IGE9aSsxbilcbiAgICAgIHggLz0gaSsxbjtcbiAgfVxuICBpZiAoeDw9MW4pIHJldHVybiBhO1xuICByZXR1cm4geDtcbn1cbmV4cG9ydCB7bWF4UHJpbWVGYWN0b3IgYXMgZ3JlYXRlc3RQcmltZUZhY3Rvcn07XG4vLyAtIGh0dHBzOi8vbWF0aHdvcmxkLndvbGZyYW0uY29tL0dyZWF0ZXN0UHJpbWVGYWN0b3IuaHRtbFxuLy8gLSBodHRwczovL3d3dy5nZWVrc2ZvcmdlZWtzLm9yZy9maW5kLWxhcmdlc3QtcHJpbWUtZmFjdG9yLW51bWJlci9cblxuXG4vKipcbiAqIEZpbmQgdGhlIHByaW1lIGZhY3RvcnMgb2YgYSBiaWdpbnQuXG4gKiBAcGFyYW0geCBhIGJpZ2ludFxuICogQHJldHVybnMgW2bigoAsIGbigoEsIC4uLl0gfCBm4bWiIGRpdmlkZXMgeCBhbmQgaXMgcHJpbWVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByaW1lRmFjdG9ycyh4OiBiaWdpbnQpOiBiaWdpbnRbXSB7XG4gIHggPSBhYnMoeCk7IGNvbnN0IGE6IGJpZ2ludFtdID0gW107XG4gIGlmICh4PD0xbikgcmV0dXJuIFtdO1xuICBpZiAoeDw9M24pIHJldHVybiBbeF07XG4gIC8vIDIuIFRyeSBmYWN0b3JzIDIsIDMuXG4gIHggPSBwdXNoUHJpbWVGYWN0b3JUbyQoYSwgeCwgMm4pO1xuICB4ID0gcHVzaFByaW1lRmFjdG9yVG8kKGEsIHgsIDNuKTtcbiAgLy8gMy4gVHJ5IGZhY3RvcnMgNmstMSwgNmsrMS5cbiAgZm9yIChsZXQgaT02biwgST0oc3FydCh4KSBhcyBiaWdpbnQpKzFuOyB4PjFuICYmIGk8PUk7IGkrPTZuKSB7XG4gICAgeCA9IHB1c2hQcmltZUZhY3RvclRvJChhLCB4LCBpLTFuKTtcbiAgICB4ID0gcHVzaFByaW1lRmFjdG9yVG8kKGEsIHgsIGkrMW4pO1xuICB9XG4gIGlmICh4PjFuKSBhLnB1c2goeCk7XG4gIHJldHVybiBhO1xufVxuXG5mdW5jdGlvbiBwdXNoUHJpbWVGYWN0b3JUbyQoYTogYmlnaW50W10sIHg6IGJpZ2ludCwgZjogYmlnaW50KTogYmlnaW50IHtcbiAgaWYgKHggJSBmIT09MG4pIHJldHVybiB4O1xuICBkbyB7XG4gICAgeCAvPSBmO1xuICB9IHdoaWxlICh4ICUgZj09PTBuKTtcbiAgYS5wdXNoKGYpO1xuICByZXR1cm4geDtcbn1cbi8vIC0gaHR0cHM6Ly93d3cuZ2Vla3Nmb3JnZWVrcy5vcmcvcHJpbWUtZmFjdG9ycy1iaWctbnVtYmVyL1xuLy8gLSBodHRwczovL21hdGh3b3JsZC53b2xmcmFtLmNvbS9QcmltZUZhY3Rvci5odG1sXG5cblxuLyoqXG4gKiBGaW5kIHRoZSBwcmltZSBmYWN0b3JzIGFuZCByZXNwZWN0aXZlIGV4cG9uZW50cyBvZiBhIGJpZ2ludC5cbiAqIEBwYXJhbSB4IGEgYmlnaW50XG4gKiBAcmV0dXJucyBbW2bigoAsIGXigoBdLCBbZuKCgSwgZeKCgV0sIC4uLl0gfCBm4bWiIGlzIGEgcHJpbWUgZmFjdG9yIG9mIHggYW5kIGXhtaIgaXMgaXRzIGV4cG9uZW50XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcmltZUV4cG9uZW50aWFscyh4OiBiaWdpbnQpOiBbYmlnaW50LCBiaWdpbnRdW10ge1xuICB4ID0gYWJzKHgpOyBjb25zdCBhOiBbYmlnaW50LCBiaWdpbnRdW10gPSBbXTtcbiAgaWYgKHg8PTFuKSByZXR1cm4gW107XG4gIGlmICh4PD0zbikgcmV0dXJuIFtbeCwgMW5dXTtcbiAgLy8gMi4gVHJ5IGZhY3RvcnMgMiwgMy5cbiAgeCA9IHB1c2hQcmltZUV4cG9uZW50aWFsVG8kKGEsIHgsIDJuKTtcbiAgeCA9IHB1c2hQcmltZUV4cG9uZW50aWFsVG8kKGEsIHgsIDNuKTtcbiAgLy8gMy4gVHJ5IGZhY3RvcnMgNmstMSwgNmsrMS5cbiAgZm9yIChsZXQgaT02biwgST0oc3FydCh4KSBhcyBiaWdpbnQpKzFuOyB4PjFuICYmIGk8PUk7IGkrPTZuKSB7XG4gICAgeCA9IHB1c2hQcmltZUV4cG9uZW50aWFsVG8kKGEsIHgsIGktMW4pO1xuICAgIHggPSBwdXNoUHJpbWVFeHBvbmVudGlhbFRvJChhLCB4LCBpKzFuKTtcbiAgfVxuICBpZiAoeD4xbikgYS5wdXNoKFt4LCAxbl0pO1xuICByZXR1cm4gYTtcbn1cblxuZnVuY3Rpb24gcHVzaFByaW1lRXhwb25lbnRpYWxUbyQoYTogW2JpZ2ludCwgYmlnaW50XVtdLCB4OiBiaWdpbnQsIGY6IGJpZ2ludCk6IGJpZ2ludCB7XG4gIGlmICh4ICUgZiE9PTBuKSByZXR1cm4geDtcbiAgbGV0IGUgPSAwbjtcbiAgZG8ge1xuICAgIHggLz0gZjsgKytlO1xuICB9IHdoaWxlICh4ICUgZj09PTBuKTtcbiAgYS5wdXNoKFtmLCBlXSk7XG4gIHJldHVybiB4O1xufVxuLy8gLSBodHRwczovL3d3dy5nZWVrc2ZvcmdlZWtzLm9yZy9wcmltZS1mYWN0b3JzLWJpZy1udW1iZXIvXG4vLyAtIGh0dHBzOi8vcmVmZXJlbmNlLndvbGZyYW0uY29tL2xhbmd1YWdlL3JlZi9GYWN0b3JJbnRlZ2VyLmh0bWxcbi8vIC0gaHR0cHM6Ly9tYXRod29ybGQud29sZnJhbS5jb20vUHJpbWVGYWN0b3JpemF0aW9uLmh0bWxcbi8vIC0gaHR0cHM6Ly9tYXRod29ybGQud29sZnJhbS5jb20vUHJpbWVGYWN0b3IuaHRtbFxuXG5cbi8qKlxuICogQ2hlY2sgaWYgYmlnaW50IGlzIHByaW1lLlxuICogQHBhcmFtIHggYSBiaWdpbnRcbiAqIEByZXR1cm5zIGlzIGRpdmlzaWJsZSBieSAxbiBhbmQgaXRzZWxmIG9ubHk/XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1ByaW1lKHg6IGJpZ2ludCk6IGJvb2xlYW4ge1xuICByZXR1cm4geCE9PTBuICYmIG1pblByaW1lRmFjdG9yKHgpID09PSBhYnMoeCk7XG59XG5cblxuLyoqXG4gKiBGaW5kIHRoZSBncmVhdGVzdCBjb21tb24gZGl2aXNvciBvZiBiaWdpbnRzLlxuICogQHBhcmFtIHhzIGEgbGlzdCBvZiBiaWdpbnRzXG4gKiBAcmV0dXJucyBnY2QoeOKCgSwgeOKCgiwgLi4uKVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2NkKC4uLnhzOiBiaWdpbnRbXSk6IGJpZ2ludCB7XG4gIGxldCBhID0geHNbMF0gfHwgMW47XG4gIGZvcihsZXQgaT0xLCBJPXhzLmxlbmd0aDsgaTxJOyBpKyspXG4gICAgYSA9IGdjZFBhaXIoYSwgeHNbaV0pO1xuICByZXR1cm4gYTtcbn1cbmV4cG9ydCB7Z2NkIGFzIGhjZn07XG5cbi8vIEZpbmQgdGhlIGdyZWF0ZXN0IGNvbW1vbiBkaXZpc29yIG9mIGEgcGFpciBvZiBiaWdpbnRzLlxuZnVuY3Rpb24gZ2NkUGFpcih4OiBiaWdpbnQsIHk6IGJpZ2ludCk6IGJpZ2ludCB7XG4gIHdoaWxlICh5IT09MG4pIHtcbiAgICBjb25zdCB0ID0geTtcbiAgICB5ID0geCAlIHk7XG4gICAgeCA9IHQ7XG4gIH1cbiAgcmV0dXJuIHg7XG59XG4vLyAtIGh0dHBzOi8vbGVtaXJlLm1lL2Jsb2cvMjAxMy8xMi8yNi9mYXN0ZXN0LXdheS10by1jb21wdXRlLXRoZS1ncmVhdGVzdC1jb21tb24tZGl2aXNvci9cbi8vIC0gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRXVjbGlkZWFuX2FsZ29yaXRobVxuXG5cbi8qKlxuICogRmluZCB0aGUgbGVhc3QgY29tbW9uIG11bHRpcGxlIG9mIGJpZ2ludHMuXG4gKiBAcGFyYW0geHMgYSBsaXN0IG9mIGJpZ2ludHNcbiAqIEByZXR1cm5zIGxjbSh44oKBLCB44oKCLCAuLi4pXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsY20oLi4ueHM6IGJpZ2ludFtdKTogYmlnaW50IHtcbiAgbGV0IGEgPSB4c1swXSB8fCAxbjtcbiAgZm9yIChsZXQgaT0xLCBJPXhzLmxlbmd0aDsgaTxJOyBpKyspXG4gICAgICBhID0gYSp4c1tpXSAvIGdjZFBhaXIoYSwgeHNbaV0pO1xuICByZXR1cm4gYTtcbn1cbi8vIC0gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTGVhc3RfY29tbW9uX211bHRpcGxlXG5cblxuXG5cbi8vIEFSUkFOR0VNRU5UU1xuLy8gLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogRmluZCB0aGUgZmFjdG9yaWFsIG9mIGEgYmlnaW50LlxuICogQHBhcmFtIG4gYSBiaWdpbnRcbiAqIEBwYXJhbSBrIGRlbm9taW5hdG9yIGZhY3RvcmlhbCBbMF1cbiAqIEByZXR1cm5zIFAobiwgayk7IGs9MDogbiEsIGs+MDogbiEvayFcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZhY3RvcmlhbChuOiBiaWdpbnQsIGs6IGJpZ2ludD0wbik6IGJpZ2ludCB7XG4gIGxldCBhID0gMW47XG4gIGlmIChuPDBuKSByZXR1cm4gMG47XG4gIGZvciAobGV0IGk9aysxbjsgaTw9bjsgaSsrKVxuICAgIGEgKj0gaTtcbiAgcmV0dXJuIGE7XG59XG4vLyAtIGh0dHBzOi8vZ2l0aHViLmNvbS9hbGF3YXR0aGUvTWF0aExpYi9ibG9iL21hc3Rlci9zcmMvRnVuY3RuL2Z1bmN0aW9ucy9mYWN0b3JpYWwudHNcbi8vIC0gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvUGVybXV0YXRpb25cblxuXG4vKipcbiAqIEZpbmQgdGhlIG51bWJlciBvZiB3YXlzIHRvIGNob29zZSBrIGVsZW1lbnRzIGZyb20gYSBzZXQgb2YgbiBlbGVtZW50cy5cbiAqIEBwYXJhbSBuIGVsZW1lbnRzIGluIHNvdXJjZSBzZXRcbiAqIEBwYXJhbSBrIGVsZW1lbnRzIGluIGNob29zZSBzZXRcbiAqIEByZXR1cm5zIEMobiwgaylcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJpbm9taWFsKG46IGJpZ2ludCwgazogYmlnaW50KTogYmlnaW50IHtcbiAgLy8gMS4gR2VuZXJhbGl6YXRpb24gdG8gbmVnYXRpdmUgaW50ZWdlcnNcbiAgaWYgKGs8MG4gfHwgaz5hYnMobikpIHJldHVybiAwbjtcbiAgaWYgKG48MG4pIHJldHVybiAoKC0xbikqKmspKmJpbm9taWFsKC1uLCBrKTtcbiAgLy8gMi4gVGFrZSBhZHZhbnRhZ2Ugb2Ygc3ltbWV0cnlcbiAgayA9IGs+bi1rPyBuLWs6aztcbiAgbGV0IGEgPSAxbiwgYiA9IDFuO1xuICBmb3IgKGxldCBpPTFuOyBpPD1rOyBpKyssIG4tLSkge1xuICAgIGEgKj0gbjtcbiAgICBiICo9IGk7XG4gIH1cbiAgcmV0dXJuIGEvYjtcbn1cbi8vIC0gaHR0cHM6Ly9naXRodWIuY29tL2FsYXdhdHRoZS9NYXRoTGliL2Jsb2IvbWFzdGVyL3NyYy9GdW5jdG4vZnVuY3Rpb25zL2Jpbm9taWFsLnRzXG4vLyAtIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Jpbm9taWFsX2NvZWZmaWNpZW50XG5cblxuLyoqXG4gKiBGaW5kIHRoZSBudW1iZXIgb2Ygd2F5cyB0byBwdXQgbiBvYmplY3RzIGluIG0gYmlucyAobj1zdW0oa+G1oikpLlxuICogQHBhcmFtIGtzIG9iamVjdHMgcGVyIGJpbiAoa+G1oilcbiAqIEByZXR1cm5zIG4hLyhr4oKBIWvigoIhLi4uKSB8IG49c3VtKGvhtaIpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtdWx0aW5vbWlhbCguLi5rczogYmlnaW50W10pOiBiaWdpbnQge1xuICBsZXQgbiA9IHN1bSguLi5rcyksIGEgPSAxbiwgYiA9IDFuO1xuICBmb3IgKGxldCBpPTAsIGo9MG4sIEk9a3MubGVuZ3RoOyBpPEk7KSB7XG4gICAgaWYgKGo8PTBuKSBqID0ga3NbaSsrXTtcbiAgICBlbHNlIHsgYSAqPSBuLS07IGIqPSBqLS07IH1cbiAgfVxuICByZXR1cm4gYS9iO1xufVxuLy8gLSBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9NdWx0aW5vbWlhbF9kaXN0cmlidXRpb25cblxuXG5cblxuLy8gR0VPTUVUUllcbi8vIC0tLS0tLS0tXG5cbi8qKlxuICogRmluZCB0aGUgbGVuZ3RoIG9mIGh5cG90ZW51c2UuXG4gKiBAcGFyYW0geHMgbGVuZ3RocyBvZiBwZXJwZW5kaWN1bGFyIHNpZGVzICh4LCB5LCB6LCAuLi4pXG4gKiBAcmV0dXJucyDiiJooeMKyICsgecKyICsgesKyKVxuICovXG5leHBvcnQgZnVuY3Rpb24gaHlwb3QoLi4ueHM6IGJpZ2ludFtdKTogYmlnaW50IHtcbiAgbGV0IGEgPSAwbjtcbiAgZm9yIChjb25zdCB4IG9mIHhzKVxuICAgIGEgKz0geCp4O1xuICByZXR1cm4gc3FydChhKSBhcyBiaWdpbnQ7XG59XG5cblxuXG5cbi8vIFNUQVRJU1RJQ1Ncbi8vIC0tLS0tLS0tLS1cblxuLyoqXG4gKiBGaW5kIHRoZSBzdW0gb2YgYmlnaW50cyAozqMpLlxuICogQHBhcmFtIHhzIGJpZ2ludHNcbiAqIEByZXR1cm5zIM6jeOG1olxuICovXG5leHBvcnQgZnVuY3Rpb24gc3VtKC4uLnhzOiBiaWdpbnRbXSk6IGJpZ2ludCB7XG4gIGxldCBhID0gMG47XG4gIGZvciAoY29uc3QgeCBvZiB4cylcbiAgICBhICs9IHg7XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogRmluZCB0aGUgcHJvZHVjdCBvZiBiaWdpbnRzICjiiI8pLlxuICogQHBhcmFtIHhzIGJpZ2ludHNcbiAqIEByZXR1cm5zIOKIj3jhtaJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByb2R1Y3QoLi4ueHM6IGJpZ2ludFtdKTogYmlnaW50IHtcbiAgbGV0IGEgPSAxbjtcbiAgZm9yIChjb25zdCB4IG9mIHhzKVxuICAgIGEgKj0geDtcbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBGaW5kIHRoZSB2YWx1ZSBzZXBhcmF0aW5nIHRoZSBoaWdoZXIgYW5kIGxvd2VyIGhhbHZlcyBvZiBiaWdpbnRzLlxuICogQHBhcmFtIHhzIGEgbGlzdCBvZiBiaWdpbnRzXG4gKiBAcmV0dXJucyB44oKYIHwgc29ydCh4cykgPSBbLi4uLCB44oKYLCAuLi5dXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtZWRpYW4oLi4ueHM6IGJpZ2ludFtdKTogYmlnaW50IHtcbiAgaWYgKHhzLmxlbmd0aD09PTApIHJldHVybiAwbjtcbiAgeHMuc29ydChjb21wYXJlKTtcbiAgY29uc3QgaSA9IHhzLmxlbmd0aD4+MTtcbiAgaWYgKCh4cy5sZW5ndGggJiAxKT09PTEpIHJldHVybiB4c1tpXTtcbiAgcmV0dXJuICh4c1tpLTFdICsgeHNbaV0pLzJuO1xufVxuLy8gLSBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy80NTMwOTQ0Ny9jYWxjdWxhdGluZy1tZWRpYW4tamF2YXNjcmlwdFxuLy8gLSBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9NZWRpYW5cblxuXG4vKipcbiAqIEZpbmQgdGhlIHZhbHVlcyB0aGF0IGFwcGVhciBtb3N0IG9mdGVuLlxuICogQHBhcmFtIHhzIGEgbGlzdCBvZiBiaWdpbnRzXG4gKiBAcmV0dXJucyBbeOKCmOKCgSwgeOKCmOKCgiwgLi4uXSB8IGNvdW50KHjigpjhtaIpIOKJpSBjb3VudCh44bWiKSDiiIAgeOG1oiDiiIggeHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1vZGVzKC4uLnhzOiBiaWdpbnRbXSk6IGJpZ2ludFtdIHtcbiAgeHMuc29ydChjb21wYXJlKTtcbiAgY29uc3QgciA9IG1heFJlcGVhdCh4cyk7XG4gIHJldHVybiBnZXRSZXBlYXRzKHhzLCByKTtcbn1cbi8vIC0gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTW9kZV8oc3RhdGlzdGljcylcblxuLy8gR2V0IHRoZSBtYXhpbXVtIG51bWJlciBvZiB0aW1lcyBhbnkgYmlnaW50IGhhcyByZXBlYXRlZCBpbiBhIHNvcnRlZCBhcnJheS5cbmZ1bmN0aW9uIG1heFJlcGVhdCh4czogYmlnaW50W10pOiBudW1iZXIge1xuICBsZXQgY291bnQgPSBNYXRoLm1pbih4cy5sZW5ndGgsIDEpLCBtYXggPSBjb3VudDtcbiAgZm9yIChsZXQgaT0xLCBJPXhzLmxlbmd0aDsgaTxJOyBpKyspIHtcbiAgICBpZiAoeHNbaS0xXT09PXhzW2ldKSBjb3VudCsrO1xuICAgIGVsc2UgeyBtYXggPSBNYXRoLm1heChtYXgsIGNvdW50KTsgY291bnQgPSAxOyB9XG4gIH1cbiAgcmV0dXJuIE1hdGgubWF4KG1heCwgY291bnQpO1xufVxuXG4vLyBHZXQgdGhlIG51bWJlcnMgd2hpY2ggaGF2ZSBiZWVuIHJlcGVhdGVkIGF0bGVhc3QgZ2l2ZW4gbnVtYmVyIG9mIHRpbWVzLlxuZnVuY3Rpb24gZ2V0UmVwZWF0cyh4czogYmlnaW50W10sIHI6IG51bWJlcik6IGJpZ2ludFtdIHtcbiAgY29uc3QgYTogYmlnaW50W10gPSBbXTsgci0tO1xuICBmb3IgKGxldCBpPTAsIEk9eHMubGVuZ3RoLXI7IGk8STsgaSsrKVxuICAgIGlmICh4c1tpXT09PXhzW2krcl0pIGEucHVzaCh4c1tpKz1yXSk7XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogRmluZCB0aGUgc21hbGxlc3QgYmlnaW50LlxuICogQHBhcmFtIHhzIGJpZ2ludHNcbiAqIEByZXR1cm5zIG1pbih4cylcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1pbiguLi54czogYmlnaW50W10pOiBiaWdpbnQge1xuICBpZiAoeHMubGVuZ3RoPT09MCkgcmV0dXJuIDBuO1xuICBsZXQgYSA9IHhzWzBdO1xuICBmb3IgKGNvbnN0IHggb2YgeHMpXG4gICAgYSA9IHg8YT8geCA6IGE7XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogRmluZCB0aGUgbGFyZ2VzdCBiaWdpbnQuXG4gKiBAcGFyYW0geHMgYmlnaW50c1xuICogQHJldHVybnMgbWF4KHhzKVxuICovXG5leHBvcnQgZnVuY3Rpb24gbWF4KC4uLnhzOiBiaWdpbnRbXSk6IGJpZ2ludCB7XG4gIGlmICh4cy5sZW5ndGg9PT0wKSByZXR1cm4gMG47XG4gIGxldCBhID0geHNbMF07XG4gIGZvciAoY29uc3QgeCBvZiB4cylcbiAgICBhID0geD5hPyB4IDogYTtcbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBGaW5kIHRoZSBtaW5pbXVtIGFuZCBtYXhpbXVtIGJpZ2ludC5cbiAqIEBwYXJhbSB4cyBiaWdpbnRzXG4gKiBAcmV0dXJucyBbbWluLCBtYXhdXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByYW5nZSguLi54czogYmlnaW50W10pOiBbYmlnaW50LCBiaWdpbnRdIHtcbiAgaWYgKHhzLmxlbmd0aD09PTApIHJldHVybiBbMG4sIDBuXTtcbiAgbGV0IGEgPSB4c1swXSwgYiA9IGE7XG4gIGZvciAoY29uc3QgeCBvZiB4cykge1xuICAgIGEgPSB4PGE/IHggOiBhO1xuICAgIGIgPSB4PmI/IHggOiBiO1xuICB9XG4gIHJldHVybiBbYSwgYl07XG59XG5cblxuLyoqXG4gKiBGaW5kIHRoZSBtZWFuIG9mIHNxdWFyZWQgZGV2aWF0aW9uIG9mIGJpZ2ludHMgZnJvbSBpdHMgbWVhbi5cbiAqIEBwYXJhbSB4cyBhIGxpc3Qgb2YgYmlnaW50c1xuICogQHJldHVybnMgz4PCsiA9IEVbKHhzIC0gwrUpwrJdIHwgwrUgPSBtZWFuKHhzKVxuICovXG5leHBvcnQgZnVuY3Rpb24gdmFyaWFuY2UoLi4ueHM6IGJpZ2ludFtdKTogYmlnaW50IHtcbiAgaWYgKHhzLmxlbmd0aD09PTApIHJldHVybiAwbjtcbiAgY29uc3QgbSA9IGFyaXRobWV0aWNNZWFuKC4uLnhzKTsgbGV0IGEgPSAwbjtcbiAgZm9yIChjb25zdCB4IG9mIHhzKVxuICAgIGEgKz0gKHgtbSkqKjJuO1xuICByZXR1cm4gYS9CaWdJbnQoeHMubGVuZ3RoKTtcbn1cbi8vIC0gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvVmFyaWFuY2VcblxuXG5cblxuLy8gTUVBTiAoU1RBVElTVElDUylcbi8vIC0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogRmluZCB0aGUgYXJpdGhtZXRpYyBtZWFuIG9mIGJpZ2ludHMgKMK1KS5cbiAqIEBwYXJhbSB4cyBiaWdpbnRzXG4gKiBAcmV0dXJucyDCtSA9ICjOo3jhtaIpL24gfCBuID0gc2l6ZSh4cylcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFyaXRobWV0aWNNZWFuKC4uLnhzOiBiaWdpbnRbXSk6IGJpZ2ludCB7XG4gIGNvbnN0IG4gPSBCaWdJbnQoeHMubGVuZ3RoKTtcbiAgcmV0dXJuIHN1bSguLi54cykvbjtcbn1cbmV4cG9ydCB7YXJpdGhtZXRpY01lYW4gYXMgbWVhbn07XG5cblxuLyoqXG4gKiBGaW5kIHRoZSBnZW9tZXRyaWMgbWVhbiBvZiBiaWdpbnRzLlxuICogQHBhcmFtIHhzIGJpZ2ludHNcbiAqIEByZXR1cm5zIOKBv+KImijiiI944bWiKSB8IG4gPSBzaXplKHhzKVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2VvbWV0cmljTWVhbiguLi54czogYmlnaW50W10pOiBiaWdpbnQgfCBudWxsIHtcbiAgY29uc3QgbiA9IEJpZ0ludCh4cy5sZW5ndGgpO1xuICByZXR1cm4gcm9vdChwcm9kdWN0KC4uLnhzKSwgbik7XG59XG5cblxuLyoqXG4gKiBGaW5kIHRoZSBoYXJtb25pYyBtZWFuIG9mIGJpZ2ludHMuXG4gKiBAcGFyYW0geHMgYmlnaW50c1xuICogQHJldHVybnMgbi/OoygxL3jhtaIpIHwgbiA9IHNpemUoeHMpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXJtb25pY01lYW4oLi4ueHM6IGJpZ2ludFtdKTogYmlnaW50IHtcbiAgY29uc3QgbiA9IEJpZ0ludCh4cy5sZW5ndGgpO1xuICBjb25zdCBwID0gcHJvZHVjdCguLi54cyk7IGxldCBxID0gMG47XG4gIGZvciAoY29uc3QgeCBvZiB4cylcbiAgICBxICs9IHAveDtcbiAgcmV0dXJuIG4qcC9xO1xufVxuXG5cbi8qKlxuICogRmluZCB0aGUgcXVhZHJpYXRpYyBtZWFuIG9mIGJpZ2ludHMuXG4gKiBAcGFyYW0geHMgYmlnaW50c1xuICogQHJldHVybnMg4oiaKM6jeOG1osKyKS9uIHwgbiA9IHNpemUoeHMpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBxdWFkcmlhdGljTWVhbiguLi54czogYmlnaW50W10pOiBiaWdpbnQge1xuICBjb25zdCBuID0gQmlnSW50KHhzLmxlbmd0aCk7XG4gIGxldCBhID0gMG47XG4gIGZvciAoY29uc3QgeCBvZiB4cylcbiAgICBhICs9IHgqeDtcbiAgcmV0dXJuIHNxcnQoYS9uKSBhcyBiaWdpbnQ7XG59XG5leHBvcnQge3F1YWRyaWF0aWNNZWFuIGFzIHJvb3RNZWFuU3F1YXJlfTtcblxuXG4vKipcbiAqIEZpbmQgdGhlIGN1YmljIG1lYW4gb2YgYmlnaW50cy5cbiAqIEBwYXJhbSB4cyBiaWdpbnRzXG4gKiBAcmV0dXJucyDCs+KImijOo3jhtaLCsykvbiB8IG4gPSBzaXplKHhzKVxuICovXG5leHBvcnQgZnVuY3Rpb24gY3ViaWNNZWFuKC4uLnhzOiBiaWdpbnRbXSk6IGJpZ2ludCB8IG51bGwge1xuICBjb25zdCBuID0gQmlnSW50KHhzLmxlbmd0aCk7XG4gIGxldCBhID0gMG47XG4gIGZvciAoY29uc3QgeCBvZiB4cylcbiAgICBhICs9IHgqKjNuO1xuICByZXR1cm4gY2JydChhL24pO1xufVxuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFVBQVU7QUFDVixVQUFVO0FBRVYsUUFBUTtBQUNSLFFBQVE7QUFFUjs7OztDQUlDLEdBQ0QsT0FBTyxTQUFTLEdBQUcsQ0FBVTtFQUMzQixPQUFPLE9BQU8sTUFBSTtBQUNwQjtBQUtBLFVBQVU7QUFDVixVQUFVO0FBRVY7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsUUFBUSxDQUFTLEVBQUUsQ0FBUztFQUMxQyxP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