extra-number
Version:
A collection for common number functions (queries, comparisons, rounding, divisors, etc).<br>
1,484 lines • 104 kB
JavaScript
//#region TYPES
/** Classification of floating point numbers. */ export var FloatClass = /*#__PURE__*/ function(FloatClass) {
/** Number is zero. */ FloatClass[FloatClass["ZERO"] = 0] = "ZERO";
/** Number is subnormal (denormal). */ FloatClass[FloatClass["SUBNORMAL"] = 16] = "SUBNORMAL";
/** Number is normal. */ FloatClass[FloatClass["NORMAL"] = 32] = "NORMAL";
/** Number is infinite. */ FloatClass[FloatClass["INFINITE"] = 48] = "INFINITE";
/** Number is NaN (not a number). */ FloatClass[FloatClass["NAN"] = 64] = "NAN";
return FloatClass;
}({});
//#endregion
//#region CONSTANTS
/** Smallest normal (not subnormal) 64-bit floating point number. */ export const MIN_NORMAL = 2.2250738585072014e-308;
/** Ratio of a circle's circumference to its diameter. */ export const TAU = 2 * Math.PI;
//#endregion
//#region ABOUT
/**
* Check if value is a number.
* @param v a value
* @returns is number?
* @example
* ```ts
* xnumber.is(3.14);
* // → true
*
* xnumber.is(NaN);
* // → true (an unexpressable number)
*
* xnumber.is('3.14');
* // → false
*
* xnumber.is({'value': 3.14});
* // → false
*
* xnumber.is(null);
* // → false
* ```
*/ export function is(v) {
return typeof v === "number";
}
/**
* Check if number is normal (not zero, subnormal, infinite, or NaN).
* @param x a number
* @returns is normal number?
* @example
* ```ts
* xnumber.isNormal(3.14);
* // → true
*
* xnumber.isNormal(0);
* // → false
*
* xnumber.isNormal(1e-320);
* // → false
*
* xnumber.isNormal(Infinity);
* // → false
*/ export function isNormal(x) {
if (x === 0) return false;
if (!Number.isFinite(x)) return false;
if (Math.abs(x) < MIN_NORMAL) return false;
return true;
}
/**
* Classify a number into its floating point category.
* @param x a number
* @returns floating point class of `x`
* @example
* ```ts
* xnumber.classify(0);
* // → FloatClass.ZERO
*
* xnumber.classify(1e-320);
* // → FloatClass.SUBNORMAL
*
* xnumber.classify(3.14);
* // → FloatClass.NORMAL
*
* xnumber.classify(Infinity);
* // → FloatClass.INFINITE
*
* xnumber.classify(NaN);
* // → FloatClass.NAN
*/ export function classify(x) {
if (x === 0) return FloatClass.ZERO;
if (Number.isNaN(x)) return FloatClass.NAN;
if (!Number.isFinite(x)) return FloatClass.INFINITE;
if (Math.abs(x) < MIN_NORMAL) return FloatClass.SUBNORMAL;
return FloatClass.NORMAL;
}
/**
* Examine if sum of divisors equals the number itself.
* @param x a number
* @returns sum of divisors(x) excluding x = x?
* @example
* ```ts
* xnumber.isPerfect(6);
* // → true (1+2+3=6)
*
* xnumber.isPerfect(28);
* // → true (1+2+4+7+14=28)
*
* xnumber.isPerfect(12);
* // → false (1+2+3+4+6=16)
*
* xnumber.isPerfect(1);
* // → false (no proper divisors)
* ```
*/ export function isPerfect(x) {
return aliquotSum(x) === x;
}
// TODO: isAlmostPerfect()?
// TODO: isSemiPerfect()?
// TODO: isQuasiPerfect()?
// TODO: isWeird()?
/**
* Examine if sum of divisors exceeds the number itself.
* @param x a number
* @returns sum of divisors(x) excluding x > x?
* @example
* ```ts
* xnumber.isAbundant(8);
* // → false (1+2+4=7 < 8)
*
* xnumber.isAbundant(15);
* // → false (1+3+5=9 < 15)
*
* xnumber.isAbundant(12);
* // → true (1+2+3+4+6=16 > 12)
*
* xnumber.isAbundant(6);
* // → false (1+2+3=6 = 6)
* ```
*/ export function isAbundant(x) {
return aliquotSum(x) > x;
}
export { isAbundant as isExcessive };
// TODO: isPrimitiveAbundant()?
// TODO: isSuperAbundant()?
/**
* Obtain the sum of divisors exceeding the number itself.
* @param x a number
* @returns sum of divisors(x) excluding x - x
* @example
* ```ts
* xnumber.abundance(12);
* // → 4 (1+2+3+4+6=16; 16-12=4)
*
* xnumber.abundance(15);
* // → -6 (1+3+5=9; 9-15=-6)
* ```
*/ export function abundance(x) {
return aliquotSum(x) - x;
}
/**
* Obtain the ratio of sum of divisors to the number itself.
* @param x a number
* @returns (sum of divisors(x)) / x
* @example
* ```ts
* xnumber.abundancyIndex(12);
* // → 2.3333... (1+2+3+4+6+12=28; 28/12=7/3)
*
* xnumber.abundancyIndex(15);
* // → 1.6 (1+3+5+15=24; 24/15=8/5)
* ```
*/ export function abundancyIndex(x) {
return (aliquotSum(x) + x) / x;
}
// TODO: areAmicable()?
// TODO: areFriendly()?
/**
* Count the number of significant digits in a number.
* @param x a number
* @returns |m - '.'| | x = m × 10ᵉ; m = mantissa, e = exponent
* @example
* ```ts
* xnumber.significantDigits(0.0034);
* // → 2
*
* xnumber.significantDigits(120.5e50);
* // → 4
*
* xnumber.significantDigits(120.5e-50);
* // → 4
* ```
*/ export function significantDigits(x) {
const a = x.toExponential();
return a.replace(/e[\+\-0-9]*$/, "").replace(/^0\.?0*|\./, "").length;
}
// - https://stackoverflow.com/questions/22884720/what-is-the-fastest-way-to-count-the-number-of-significant-digits-of-a-number
//#endregion
//#region COMPARE
/**
* Compare two numbers.
* @param x a number
* @param y another number
* @returns x<y: -ve, x=y: 0, x>y: +ve
* @example
* ```ts
* xnumber.compare(10, 12);
* // → -2 (-ve)
*
* xnumber.compare(12, 12);
* // → 0
*
* xnumber.compare(17, 12);
* // → 5 (+ve)
* ```
*/ export function compare(x, y) {
return x - y;
}
/**
* Check if two numbers are unordered (NaN involved).
* @param x a number
* @param y another number
* @returns x=NaN or y=NaN?
* @example
* ```ts
* xnumber.isUnordered(10, NaN);
* // → true
*
* xnumber.isUnordered(NaN, 12);
* // → true
*
* xnumber.isUnordered(10, 12);
* // → false
*
* xnumber.isUnordered(NaN, NaN);
* // → true
* ```
*/ export function isUnordered(x, y) {
return Number.isNaN(x) || Number.isNaN(y);
}
//#endregion
//#region SIGN
/**
* Copy the sign of a number to another number.
* @param mag number whose magnitude is to be copied
* @param sgn sign of the number to copy
* @returns `|mag|` with sign of `sgn`
* @example
* ```ts
* xnumber.copySign(3.14, -1);
* // → -3.14
*
* xnumber.copySign(-3.14, 1);
* // → 3.14
*
* xnumber.copySign(-6.28, -1);
* // → -6.28
*/ export function copySign(mag, sgn) {
return Math.sign(sgn) === Math.sign(mag) ? mag : -mag;
}
//#endregion
//#region ROUND
/**
* Round down a number to specific precision.
* @param x a number
* @param pre to precision [1]
* @example
* ```ts
* xnumber.floor(9.161, 1);
* // → 9
*
* xnumber.floor(9.161, 0.01);
* // → 9.16
*
* xnumber.floor(9.1617, 0.05);
* // → 9.15
* ```
*/ export function floor(x, pre = 1) {
return Math.floor(x / pre) * pre;
}
/**
* Round up a number to specific precision.
* @param x a number
* @param pre to precision [1]
* @example
* ```ts
* xnumber.ceil(9.121, 1);
* // → 10
*
* xnumber.ceil(9.121, 0.01);
* // → 9.13
*
* xnumber.ceil(9.1217, 0.05);
* // → 9.15
* ```
*/ export function ceil(x, pre = 1) {
return Math.ceil(x / pre) * pre;
}
/**
* Round a number to specific precision.
* @param x a number
* @param pre to precision [1]
* @example
* ```ts
* xnumber.round(9.135, 1);
* // → 9
*
* xnumber.round(9.135, 1e-2);
* // → 9.14
*
* xnumber.round(9.1357, 0.05);
* // → 9.15
*
* 0.1 + 0.2
* // → 0.30000000000000004 (why?)
*
* xnumber.round(0.1 + 0.2, 1e-12);
* // → 0.3 (nice!)
* ```
*/ export function round(x, pre = 1) {
return Math.round(x / pre) * pre;
}
/**
* Perform floor-divison of two numbers.
* @param x divisor
* @param y dividend
* @returns ⌊x/y⌋
* @example
* ```ts
* xnumber.floorDiv(15, 4);
* // → 3
*
* xnumber.floorDiv(2, 2);
* // → 1
*
* xnumber.floorDiv(-15, 4);
* // → -4
* ```
*/ export function floorDiv(x, y) {
return Math.floor(x / y);
}
/**
* Perform ceiling-divison of two numbers.
* @param x divisor
* @param y dividend
* @returns ⌈x/y⌉
* @example
* ```ts
* xnumber.ceilDiv(15, 4);
* // → 4
*
* xnumber.ceilDiv(2, 2);
* // → 1
*
* xnumber.ceilDiv(-15, 4);
* // → -3
* ```
*/ export function ceilDiv(x, y) {
return Math.ceil(x / y);
}
/**
* Perform rounded-divison of two numbers.
* @param x divisor
* @param y dividend
* @returns [x/y]
* @example
* ```ts
* xnumber.roundDiv(15, 4);
* // → 4
*
* xnumber.roundDiv(2, 2);
* // → 1
*
* xnumber.roundDiv(-15, 4);
* // → -4
* ```
*/ export function roundDiv(x, y) {
return Math.round(x / y);
}
//#endregion
//#region MODULO
/**
* Find the remainder of x/y with sign of x (truncated division).
* @param x dividend
* @param y divisor
* @returns trunc(x % y)
* @example
* ```ts
* xnumber.rem(1, 10);
* // → 1
*
* xnumber.rem(-1, 10);
* // → -1
*
* xnumber.rem(1, -10);
* // → 1
* ```
*/ 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)
* @example
* ```ts
* xnumber.mod(1, 10);
* // → 1
*
* xnumber.mod(-1, 10);
* // → 9
*
* xnumber.mod(1, -10);
* // → -9
* ```
*/ export function mod(x, y) {
return x - y * Math.floor(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 n>0: floor(x % y), n<0: ceil(x % y)
* @example
* ```ts
* xnumber.modp(1, 10);
* // → 1
*
* xnumber.modp(-1, 10);
* // → 9
*
* xnumber.modp(1, -10);
* // → 1
* ```
*/ export function modp(x, y) {
return x - Math.abs(y) * Math.floor(x / Math.abs(y));
}
// - https://en.wikipedia.org/wiki/Modulo_operation
//#endregion
//#region RANGE CONTROL
/**
* Constrain a number within a minimum and a maximum value.
* @param x a number
* @param min minimum value
* @param max maximum value
* @returns x<min: min, x>max: max, x
* @example
* ```ts
* xnumber.constrain(20, 0, 50);
* // → 20
*
* xnumber.constrain(-10, 0, 100);
* // → 0
*
* xnumber.constrain(120, 0, 100);
* // → 100
* ```
*/ export function constrain(x, min, max) {
return Math.min(Math.max(x, min), max);
}
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)
/**
* Normalize a number from its current range into a value between 0 and 1.
* @param x a number
* @param r lower bound of current range
* @param R upper bound of current range
* @returns ∈ [0, 1]
* @example
* ```ts
* xnumber.normalize(20, 0, 50);
* // → 0.4
*
* xnumber.normalize(-10, 0, 100);
* // → -0.1
* ```
*/ export function normalize(x, r, R) {
return (x - r) / (R - r);
}
export { normalize as norm };
// - https://processing.org/reference/norm_.html
/**
* Re-map a number from one range to another.
* @param x a number
* @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]
* @example
* ```ts
* xnumber.remap(25, 0, 100, 0, 1366);
* // → 341.5
*
* xnumber.remap(110, 0, 100, -20, -10);
* // → -9
* ```
*/ export function remap(x, r, R, t, T) {
return t + (x - r) / (R - r) * (T - t);
}
export { remap as map };
// - https://processing.org/reference/map_.html
/**
* Linearly interpolate a number between two numbers.
* @param x start number
* @param y stop number
* @param t interpolant ∈ [0, 1]
* @returns ∈ [x, y]
* @example
* ```ts
* xnumber.lerp(80, 320, 0.8);
* // → 272
*
* xnumber.lerp(80, 320, 0.20);
* // → 128
*
* xnumber.lerp(80, 320, 0.32);
* // → 156.8
* ```
*/ export function lerp(x, y, t) {
return x + t * (y - x);
}
// - https://processing.org/reference/lerp_.html
// - https://docs.unity3d.com/ScriptReference/Vector3.Lerp.html
//#endregion
//#region FRACTIONAL
/**
* Make a number purely fractional, by shifting the decimal point.
* @param x a number
* @param n maximum number of digits to shift (-1: all) [20]
* @returns fractional number
* @example
* ```ts
* xnumber.fractionize(123);
* // → 0.123
*
* xnumber.fractionize(-9876, 3);
* // → -0.988
*
* xnumber.fractionize(0.001234, 3);
* // → 0.001
* ```
*/ export function fractionize(x, n = 20) {
const xp = Math.abs(x);
const xdig = xp < 1 ? 0 : 1 + Math.floor(Math.log10(xp));
if (n < 0) return x * Math.pow(10, -xdig);
return Math.round(x * Math.pow(10, n - xdig)) * Math.pow(10, -n);
}
/**
* Make a number purely integer, by shifting the decimal point.
* @param x a number
* @param n maximum number of digits to shift (-1: all) [20]
* @returns integer number
* @example
* ```ts
* xnumber.defractionize(0.123);
* // → 123
*
* xnumber.defractionize(-0.988, 2);
* // → -99
*
* xnumber.defractionize(12.345, 2);
* // → 1235
* ```
*/ export function defractionize(x, n = 20) {
let xp = Math.abs(x), i = 0;
for(; n < 0 || i < n;){
xp *= 10;
++i;
if (xp % 1 === 0) break;
}
return Math.round(x * Math.pow(10, i));
}
//#endregion
//#region ARITHMETIC
/**
* Check if a number is a power-of-n.
* @param x a number
* @param n base
* @returns nⁱ = x? | i = +ve integer
* @example
* ```ts
* xnumber.isPow(32, 2);
* // → true
*
* xnumber.isPow(32, 4);
* // → false
*
* xnumber.isPow(64, 4);
* // → true
* ```
*/ export function isPow(x, n) {
if (n === 0) return x === 0;
const p = log(Math.abs(x), Math.abs(n));
if (p !== Math.floor(p)) return false;
return x < 0 ? n < 0 && (p & 1) === 1 : n > 0 || (p & 1) === 0;
}
/**
* Find largest power-of-n less than or equal to given number.
* @param x a number
* @param n base
* @returns nⁱ | nⁱ ≤ x and nⁱ > x/n
* @example
* ```ts
* xnumber.prevPow(32, 2);
* // → 32
*
* xnumber.prevPow(35, 2);
* // → 32
*
* xnumber.prevPow(35, 3);
* // → 27
* ```
*/ export function prevPow(x, n) {
if (x <= 1) return 0;
const p = Math.floor(Math.log(x) / Math.log(n));
return Math.pow(n, p);
}
/**
* Find smallest power-of-n greater than or equal to given number.
* @param x a number
* @param n base
* @returns nⁱ | nⁱ ≥ x and nⁱ < n*x
* @example
* ```ts
* xnumber.nextPow(32, 2);
* // → 32
*
* xnumber.nextPow(29, 2);
* // → 32
*
* xnumber.nextPow(29, 3);
* // → 81
* ```
*/ export function nextPow(x, n) {
if (x <= 0) return 1;
const p = Math.ceil(Math.log(x) / Math.log(n));
return Math.pow(n, p);
}
/**
* Find the nth root of a number (ⁿ√).
* @param x a number
* @param n root
* @returns ⁿ√x
* @example
* ```ts
* xnumber.root(25, 2);
* // → 5
*
* xnumber.root(-8, 3);
* // → -2
* ```
*/ export function root(x, n) {
if ((n & 1) === 0) return Math.pow(x, 1 / n);
return Math.sign(x) * Math.pow(Math.abs(x), 1 / n);
}
// - https://github.com/alawatthe/MathLib/blob/master/src/Functn/functions/root.ts
/**
* Find the logarithm of a number with a given base.
* @param x a number
* @param b logarithm base [e]
* @returns log_b (x)
* @example
* ```ts
* xnumber.log(Math.E);
* // → 1
*
* xnumber.log(10);
* // → 2.302585092994046
*
* xnumber.log(243, 3);
* // → 5
*
* xnumber.log(64, 2);
* // → 6
* ```
*/ export function log(x, b = Math.E) {
return Math.log(x) / Math.log(b);
}
// - https://en.wikipedia.org/wiki/Logarithm
//#endregion
//#region DIVISORS
/**
* List all divisors of a number, except itself.
* @param x a number
* @returns proper divisors (factors)
* @example
* ```ts
* xnumber.properDivisors(6);
* // → [1, 2, 3]
*
* xnumber.properDivisors(1);
* // → []
*
* xnumber.properDivisors(0);
* // → []
*
* xnumber.properDivisors(-24);
* // → [1, 2, 3, 4, 6, 8, 12]
* ```
*/ export function properDivisors(x) {
const a = [];
x = Math.abs(x);
for(let i = 1; i < x; i++)if (x % i === 0) 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 number.
* @param x a number
* @returns Σdᵢ | dᵢ is a divisor of x and ≠x
* @example
* ```ts
* xnumber.aliquotSum(6);
* // → 6 (1+2+3)
*
* xnumber.aliquotSum(1);
* // → 0
*
* xnumber.aliquotSum(0);
* // → 0
*
* xnumber.aliquotSum(-24);
* // → 36 (1+2+3+4+6+8+12)
* ```
*/ export function aliquotSum(x) {
let a = 0;
x = Math.abs(x);
for(let i = 0; i < x; i++)if (x % i === 0) a += i;
return a;
}
/**
* Find the least prime number which divides a number.
* @param x a number
* @returns least prime factor
* @example
* ```ts
* xnumber.minPrimeFactor(1);
* // → 0
*
* xnumber.minPrimeFactor(3);
* // → 3
*
* xnumber.minPrimeFactor(21);
* // → 3
*
* xnumber.minPrimeFactor(55);
* // → 5
*
* xnumber.minPrimeFactor(53);
* // → 53
* ```
*/ export function minPrimeFactor(x) {
x = Math.abs(x);
// 1. LPF of 2, 3 is the number itself.
if (x <= 1) return 0;
if (x <= 3) return x;
// 2. LPF for multiples of 2, 3.
if (x % 2 === 0) return 2;
if (x % 3 === 0) return 3;
// 3. LPF can be 6k-1 or 6k+1.
for(let i = 6, I = Math.sqrt(x) + 1; i <= I; i += 6){
if (x % (i - 1) === 0) return i - 1;
if (x % (i + 1) === 0) return i + 1;
}
return x;
}
export { minPrimeFactor as leastPrimeFactor };
// - https://mathworld.wolfram.com/LeastPrimeFactor.html
/**
* Find the greatest prime number which divides a number.
* @param x a number
* @returns greatest prime factor
* @example
* ```ts
* xnumber.maxPrimeFactor(1);
* // → 0
*
* xnumber.maxPrimeFactor(3);
* // → 3
*
* xnumber.maxPrimeFactor(21);
* // → 7
*
* xnumber.maxPrimeFactor(55);
* // → 11
*
* xnumber.maxPrimeFactor(53);
* // → 53
* ```
*/ export function maxPrimeFactor(x) {
let a = 0;
x = Math.abs(x);
// 1. GPF of 2, 3 is the number itself.
if (x <= 1) return 0;
if (x <= 3) return x;
// 2. Remove factors 2, 3.
for(; x % 2 === 0; a = 2)x /= 2;
for(; x % 3 === 0; a = 3)x /= 3;
// 3. Remove factors 6k-1, 6k+1.
for(let i = 6, I = Math.sqrt(x) + 1; x > 1 && i <= I; i += 6){
for(; x % (i - 1) === 0; a = i - 1)x /= i - 1;
for(; x % (i + 1) === 0; a = i + 1)x /= i + 1;
}
if (x <= 1) 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 number.
* @param x a number
* @returns [f₀, f₁, ...] | fᵢ divides x and is prime
* @example
* ```ts
* xnumber.primeFactors(1);
* // → []
*
* xnumber.primeFactors(3);
* // → [3]
*
* xnumber.primeFactors(21);
* // → [3, 7]
*
* xnumber.primeFactors(55);
* // → [5, 11]
*
* xnumber.primeFactors(53);
* // → [53]
* ```
*/ export function primeFactors(x) {
const a = [];
x = Math.abs(x);
if (x <= 1) return [];
if (x <= 3) return [
x
];
// 2. Try factors 2, 3.
x = pushPrimeFactorTo$(a, x, 2);
x = pushPrimeFactorTo$(a, x, 3);
// 3. Try factors 6k-1, 6k+1.
for(let i = 6, I = Math.sqrt(x) + 1; x > 1 && i <= I; i += 6){
x = pushPrimeFactorTo$(a, x, i - 1);
x = pushPrimeFactorTo$(a, x, i + 1);
}
if (x > 1) a.push(x);
return a;
}
function pushPrimeFactorTo$(a, x, f) {
if (x % f !== 0) return x;
do {
x /= f;
}while (x % f === 0)
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 number.
* @param x a number
* @returns [[f₀, e₀], [f₁, e₁], ...] | fᵢ is a prime factor of x and eᵢ is its exponent
* @example
* ```ts
* xnumber.primeExponentials(1);
* // → []
*
* xnumber.primeExponentials(9);
* // → [[3, 2]]
*
* xnumber.primeExponentials(63);
* // → [[3, 2], [7, 1]]
*
* xnumber.primeExponentials(605);
* // → [[5, 1], [11, 2]]
*
* xnumber.primeExponentials(53);
* // → [[53, 1]]
* ```
*/ export function primeExponentials(x) {
const a = [];
x = Math.abs(x);
if (x <= 1) return [];
if (x <= 3) return [
[
x,
1
]
];
// 2. Try factors 2, 3.
x = pushPrimeExponentialTo$(a, x, 2);
x = pushPrimeExponentialTo$(a, x, 3);
// 3. Try factors 6k-1, 6k+1.
for(let i = 6, I = Math.sqrt(x) + 1; x > 1 && i <= I; i += 6){
x = pushPrimeExponentialTo$(a, x, i - 1);
x = pushPrimeExponentialTo$(a, x, i + 1);
}
if (x > 1) a.push([
x,
1
]);
return a;
}
function pushPrimeExponentialTo$(a, x, f) {
if (x % f !== 0) return x;
let e = 0;
do {
x /= f;
++e;
}while (x % f === 0)
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
/**
* Examine if number is prime.
* @param x a number
* @returns is divisible by 1 and itself only?
* @example
* ```ts
* xnumber.isPrime(7);
* // → true
*
* xnumber.isPrime(53);
* // → true
*
* xnumber.isPrime(4);
* // → false
*
* xnumber.isPrime(1);
* // → false
*
* xnumber.isPrime(0);
* // → false
* ```
*/ export function isPrime(x) {
return x !== 0 && minPrimeFactor(x) === Math.abs(x);
}
/**
* Find the greatest common divisor of numbers.
* @param xs a list of numbers
* @returns gcd(x₁, x₂, ...)
* @example
* ```ts
* xnumber.gcd(6, 15);
* // → 3
*
* xnumber.gcd(6, 15, 21);
* // → 3
*
* xnumber.gcd(6, 15, 20);
* // → 1
* ```
*/ export function gcd(...xs) {
let a = xs[0] || 1;
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 numbers.
function gcdPair(x, y) {
while(y !== 0){
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 numbers.
* @param xs a list of numbers
* @returns lcm(x₁, x₂, ...)
* @example
* ```ts
* xnumber.lcm(2, 3);
* // → 6
*
* xnumber.lcm(2, 3, 4);
* // → 12
*
* xnumber.lcm(2, 3, 4, 5);
* // → 60
* ```
*/ export function lcm(...xs) {
let a = xs[0] || 1;
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
//#endregion
//#region ARRANGEMENTS
/**
* Find the factorial of a number.
* @param n a number
* @param k denominator factorial [0]
* @returns P(n, k); k=0: n!, k>0: n!/k!
* @example
* ```ts
* xnumber.factorial(5);
* // → 120
*
* xnumber.factorial(6);
* // → 720
*
* xnumber.factorial(7);
* // → 5040
* ```
*/ export function factorial(n, k = 0) {
if (n < 0) return 0;
let a = 1;
for(let i = k + 1; 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)
* @example
* ```ts
* xnumber.binomial(4, 1);
* // → 4
*
* xnumber.binomial(4, 2);
* // → 6
*
* xnumber.binomial(4, 3);
* // → 4
* ```
*/ export function binomial(n, k) {
// 1. Generalization to negative integers
if (k < 0 || k > Math.abs(n)) return 0;
if (n < 0) return Math.pow(-1, k) * binomial(-n, k);
// 2. Take advantage of symmetry
k = k > n - k ? n - k : k;
let a = 1;
for(let i = 1; i <= k; i++, n--)a *= n / i;
return a;
}
// - 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ᵢ)
* @example
* ```ts
* xnumber.multinomial(1, 2);
* // → 3
*
* xnumber.multinomial(1, 2, 3);
* // → 60
*
* xnumber.multinomial(1, 2, 3, 4);
* // → 12600
* ```
*/ export function multinomial(...ks) {
let n = sum(...ks), a = 1;
for(let i = 0, j = 0, I = ks.length; i < I;){
if (j <= 0) j = ks[i++];
else a *= n-- / j--;
}
return a;
}
// - https://en.wikipedia.org/wiki/Multinomial_distribution
//#endregion
//#region GEOMETRY
/**
* Convert radians to degrees.
* @param x radians
* @returns 2π → 360
* @example
* ```ts
* xnumber.degrees(3);
* // → 171.88733853924697
*
* xnumber.degrees(1);
* // → 57.29577951308232
* ```
*/ export function degrees(x) {
return x * (180 / Math.PI);
}
// - https://processing.org/reference/degrees_.html
/**
* Convert degrees to radians.
* @param x degrees
* @returns 360 → 2π
* @example
* ```ts
* xnumber.radians(180);
* // → 3.141592653589793
*
* xnumber.radians(60);
* // → 1.0471975511965976
* ```
*/ export function radians(x) {
return x * (Math.PI / 180);
}
// - https://processing.org/reference/radians_.html
//#endregion
//#region STATISTICS
/**
* Find the sum of numbers (Σ).
* @param xs a list of numbers
* @returns Σxᵢ
* @example
* ```ts
* xnumber.sum(1, 2);
* // → 3
*
* xnumber.sum(1, 2, 3);
* // → 6
*
* xnumber.sum(1, 2, 3, 4);
* // → 10
* ```
*/ export function sum(...xs) {
let a = 0;
for (const x of xs)a += x;
return a;
}
/**
* Find the product of numbers (∏).
* @param xs a list of numbers
* @returns ∏xᵢ
* @example
* ```ts
* xnumber.product(1, 2);
* // → 2
*
* xnumber.product(1, 2, 3);
* // → 6
*
* xnumber.product(1, 2, 3, 4);
* // → 24
* ```
*/ export function product(...xs) {
let a = 1;
for (const x of xs)a *= x;
return a;
}
/**
* Find the value separating the higher and lower halves of numbers.
* @param xs a list of numbers
* @returns xₘ | sort(xs) = [..., xₘ, ...]
* @example
* ```ts
* xnumber.median(1, 7);
* // → 4
*
* xnumber.median(1, 7, 8);
* // → 7
*
* xnumber.median(1, 7, 8, 10);
* // → 7.5
* ```
*/ export function median(...xs) {
if (xs.length === 0) return 0;
xs.sort((a, b)=>a - b);
const i = xs.length >> 1;
if ((xs.length & 1) === 1) return xs[i];
return (xs[i - 1] + xs[i]) / 2;
}
// - 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 numbers
* @returns [xₘ₁, xₘ₂, ...] | count(xₘᵢ) ≥ count(xᵢ) ∀ xᵢ ∈ xs
* @example
* ```ts
* xnumber.modes(1, 2);
* // → [1, 2]
*
* xnumber.modes(1, 2, 2);
* // → [2]
*
* xnumber.modes(1, 2, 2, 3, 3);
* // → [2, 3]
* ```
*/ export function modes(...xs) {
xs.sort((a, b)=>a - b);
const r = maxRepeat(xs);
return getRepeats(xs, r);
}
// - https://en.wikipedia.org/wiki/Mode_(statistics)
// Get the maximum number of times any number 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 and largest values.
* @param xs a list of numbers
* @returns [min(xs), max(xs)]
* @example
* ```ts
* xnumber.range(1, 7);
* // → 6
*
* xnumber.range(1, 7, 6);
* // → 6
*
* xnumber.range(1, 7, 8, 6);
* // → 7
* ```
*/ export function range(...xs) {
return [
Math.min(...xs),
Math.max(...xs)
];
}
// - https://en.wikipedia.org/wiki/Range_(statistics)
/**
* Find the mean of squared deviation of numbers from its mean.
* @param xs a list of numbers
* @returns σ² = E[(xs - µ)²] | µ = mean(xs)
* @example
* ```ts
* xnumber.variance(1, 2);
* // → 0.25
*
* xnumber.variance(1, 2, 3);
* // → 0.6666666666666666
*
* xnumber.variance(1, 2, 3, 4);
* // → 1.25
* ```
*/ export function variance(...xs) {
if (xs.length === 0) return 0;
const m = arithmeticMean(...xs);
let a = 0;
for (const x of xs)a += (x - m) ** 2;
return a / xs.length;
}
// - https://en.wikipedia.org/wiki/Variance
//#endregion
//#region MEAN (STATISTICS)
/**
* Find the average of numbers.
* @param xs a list of numbers
* @returns Σxᵢ/n | n = size(xs)
* @example
* ```ts
* xnumber.arithmethicMean(1, 2);
* // → 1.5
*
* xnumber.arithmethicMean(1, 2, 3);
* // → 2
*
* xnumber.arithmethicMean(1, 2, 3, 4);
* // → 2.5
* ```
*/ export function arithmeticMean(...xs) {
if (xs.length === 0) return 0;
return sum(...xs) / xs.length;
}
export { arithmeticMean as mean };
/**
* Find the geometric mean of numbers.
* @param xs a list of numbers
* @returns ⁿ√(∏xᵢ) | n = size(xs)
* @example
* ```ts
* xnumber.geometricMean(1, 2);
* // → 1.4142135623730951 (Math.sqrt(2))
*
* xnumber.geometricMean(1, 2, 3);
* // → 1.8171205928321397 (Math.cbrt(6))
*
* xnumber.geometricMean(1, 2, 3, 4);
* // → 2.2133638394006434 (Math.pow(24, 1/4))
* ```
*/ export function geometricMean(...xs) {
const n = xs.length;
return root(product(...xs), n);
}
/**
* Find the harmonic mean of numbers.
* @param xs a list of numbers
* @returns n/Σ(1/xᵢ) | n = size(xs)
* @example
* ```ts
* xnumber.harmonicMean(1, 2);
* // → 1.3333333333333333 (4/3)
*
* xnumber.harmonicMean(1, 2, 3);
* // → 1.6363636363636365 (18/11)
*
* xnumber.harmonicMean(1, 2, 3, 4);
* // → 1.92 (48/25)
* ```
*/ export function harmonicMean(...xs) {
const n = xs.length;
const p = product(...xs);
let q = 0;
for (const x of xs)q += p / x;
return n * p / q;
}
/**
* Find the quadriatic mean of numbers.
* @param xs a list of numbers
* @returns √(Σxᵢ²)/n | n = size(xs)
* @example
* ```ts
* xnumber.quadriaticMean(1, 2);
* // → 1.5811388300841898 (Math.sqrt(5/2))
*
* xnumber.quadriaticMean(1, 2, 3);
* // → 2.160246899469287 (Math.sqrt(14/3))
*
* xnumber.quadriaticMean(1, 2, 3, 4);
* // → 2.7386127875258306 (Math.sqrt(30/4))
* ```
*/ export function quadriaticMean(...xs) {
const n = xs.length;
let a = 0;
for (const x of xs)a += x * x;
return Math.sqrt(a / n);
}
export { quadriaticMean as rootMeanSquare };
/**
* Find the cubic mean of numbers.
* @param xs a list of numbers
* @returns ³√(Σxᵢ³)/n | n = size(xs)
* @example
* ```ts
* xnumber.cubicMean(1, 2);
* // → 1.6509636244473134 (Math.cbrt(9/2))
*
* xnumber.cubicMean(1, 2, 3);
* // → 2.2894284851066637 (Math.cbrt(36/3))
*
* xnumber.cubicMean(1, 2, 3, 4);
* // → 2.924017738212866 (Math.cbrt(100/4))
* ```
*/ export function cubicMean(...xs) {
const n = xs.length;
let a = 0;
for (const x of xs)a += x ** 3;
return Math.cbrt(a / n);
}
//#endregion
//#region ROMAN NUMERALS
/** List of symbols in the Roman numeral system. */ const ROMAN_SYMBOLS = [
'I',
'IV',
'V',
'IX',
'X',
'XL',
'L',
'XC',
'C',
'CD',
'D',
'CM',
'M'
];
/** Respective values in the Roman numeral system. */ const ROMAN_VALUES = [
1,
4,
5,
9,
10,
40,
50,
90,
100,
400,
500,
900,
1000
];
/** Maximum power-of-10 representable in Roman numerals. */ const ROMAN_MAX_POW10 = 3;
/**
* Convert roman numerals to number.
* @param txt roman numerals
* @returns eg. XCV -> 95, IV.V -> 4.5, IXe+II -> 900
* @example
* ```ts
* xnumber.fromRomanNumerals('XCV');
* // → 95
*
* xnumber.fromRomanNumerals('IV.V');
* // → 4.5
*
* xnumber.fromRomanNumerals('IXe+II');
* // → 900
* ```
*/ export function fromRomanNumerals(txt) {
const m = /^\s*(-?[\sIVXLCDM]+)\s*(?:\.([\sIVXLCDM]+))?(?:E[-+]([\sIVXLCDM]+))?\s*$/i.exec(txt) || [];
const aint = fromRomanInteger(m[1]);
const afrc = m[2] ? fromRomanInteger(m[2]) : 0;
const aexp = m[3] ? fromRomanInteger(m[3]) : 0;
return Math.sign(aint) * (Math.abs(aint) + fractionize(afrc)) * Math.pow(10, aexp);
}
export { fromRomanNumerals as fromRoman };
function fromRomanInteger(txt) {
let s = ROMAN_SYMBOLS.length - 1;
const n = txt.search(/^\s*-/) >= 0;
let a = 0;
txt = txt.replace(/\W/g, '').toUpperCase();
for(let i = 0, I = txt.length; i < I; i += ROMAN_SYMBOLS[s].length){
while(s >= 0 && txt.substring(i, i + ROMAN_SYMBOLS[s].length) !== ROMAN_SYMBOLS[s])--s;
if (s < 0) break;
a += ROMAN_VALUES[s];
}
return n ? -a : a;
}
/**
* Convert number to roman numerals.
* @param x a number
* @param exp use exponential/scientific notation [false]
* @returns eg. 95 -> XCV, 4.5 -> IV.V, 900 -> IXe+II (scientific = true)
* @example
* ```ts
* xnumber.toRomanNumerals(95);
* // → 'XCV'
*
* xnumber.toRomanNumerals(4.5);
* // → 'IV.V'
*
* xnumber.toRomanNumerals(900, true);
* // → 'IXe+II'
* ```
*/ export function toRomanNumerals(x, exp = false) {
const xp = Math.abs(x);
// Let's get the exponent and mantissa.
const xexp = Math.floor(Math.log10(xp));
const dexp = exp || xexp > ROMAN_MAX_POW10 ? xexp : 0;
const dman = xp * Math.pow(10, -dexp);
const dfrc = defractionize(dman % 1, ROMAN_MAX_POW10);
const dint = Math.sign(x) * Math.floor(dman);
// Now, convert to roman numerals.
const aman = toRomanInteger(dint) + (dfrc ? '.' + toRomanInteger(dfrc) : '');
const aexp = dexp !== 0 ? 'e' + (dexp > 0 ? '+' : '') + toRomanInteger(dexp) : '';
return aman + aexp;
}
export { toRomanNumerals as toRoman };
export function toRomanInteger(x) {
let a = x < 0 ? '-' : '';
x = Math.abs(x);
for(let s = ROMAN_SYMBOLS.length - 1; s >= 0; --s)while(x >= ROMAN_VALUES[s]){
x -= ROMAN_VALUES[s];
a += ROMAN_SYMBOLS[s];
}
return a;
} //#endregion
// export {default as fromScientific} from './_fromScientific';
// export {default as toScientific} from './_toScientific';
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9leHRyYS1udW1iZXIvZXh0cmEtbnVtYmVyL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vI3JlZ2lvbiBUWVBFU1xuLyoqIENsYXNzaWZpY2F0aW9uIG9mIGZsb2F0aW5nIHBvaW50IG51bWJlcnMuICovXG5leHBvcnQgZW51bSBGbG9hdENsYXNzIHtcbiAgLyoqIE51bWJlciBpcyB6ZXJvLiAqL1xuICBaRVJPICAgICAgPSAweDAwLFxuICAvKiogTnVtYmVyIGlzIHN1Ym5vcm1hbCAoZGVub3JtYWwpLiAqL1xuICBTVUJOT1JNQUwgPSAweDEwLFxuICAvKiogTnVtYmVyIGlzIG5vcm1hbC4gKi9cbiAgTk9STUFMICAgID0gMHgyMCxcbiAgLyoqIE51bWJlciBpcyBpbmZpbml0ZS4gKi9cbiAgSU5GSU5JVEUgID0gMHgzMCxcbiAgLyoqIE51bWJlciBpcyBOYU4gKG5vdCBhIG51bWJlcikuICovXG4gIE5BTiAgICAgICA9IDB4NDAsXG59XG4vLyNlbmRyZWdpb25cblxuXG5cblxuLy8jcmVnaW9uIENPTlNUQU5UU1xuLyoqIFNtYWxsZXN0IG5vcm1hbCAobm90IHN1Ym5vcm1hbCkgNjQtYml0IGZsb2F0aW5nIHBvaW50IG51bWJlci4gKi9cbmV4cG9ydCBjb25zdCBNSU5fTk9STUFMID0gMi4yMjUwNzM4NTg1MDcyMDE0ZS0zMDg7XG4vKiogUmF0aW8gb2YgYSBjaXJjbGUncyBjaXJjdW1mZXJlbmNlIHRvIGl0cyBkaWFtZXRlci4gKi9cbmV4cG9ydCBjb25zdCBUQVUgPSAyICogTWF0aC5QSTtcbi8vI2VuZHJlZ2lvblxuXG5cblxuXG4vLyNyZWdpb24gQUJPVVRcbi8qKlxuICogQ2hlY2sgaWYgdmFsdWUgaXMgYSBudW1iZXIuXG4gKiBAcGFyYW0gdiBhIHZhbHVlXG4gKiBAcmV0dXJucyBpcyBudW1iZXI/XG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIHhudW1iZXIuaXMoMy4xNCk7XG4gKiAvLyDihpIgdHJ1ZVxuICpcbiAqIHhudW1iZXIuaXMoTmFOKTtcbiAqIC8vIOKGkiB0cnVlIChhbiB1bmV4cHJlc3NhYmxlIG51bWJlcilcbiAqXG4gKiB4bnVtYmVyLmlzKCczLjE0Jyk7XG4gKiAvLyDihpIgZmFsc2VcbiAqXG4gKiB4bnVtYmVyLmlzKHsndmFsdWUnOiAzLjE0fSk7XG4gKiAvLyDihpIgZmFsc2VcbiAqXG4gKiB4bnVtYmVyLmlzKG51bGwpO1xuICogLy8g4oaSIGZhbHNlXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzKHY6IHVua25vd24pOiB2IGlzIG51bWJlciB7XG4gIHJldHVybiB0eXBlb2YgdiA9PT0gXCJudW1iZXJcIjtcbn1cblxuXG4vKipcbiAqIENoZWNrIGlmIG51bWJlciBpcyBub3JtYWwgKG5vdCB6ZXJvLCBzdWJub3JtYWwsIGluZmluaXRlLCBvciBOYU4pLlxuICogQHBhcmFtIHggYSBudW1iZXJcbiAqIEByZXR1cm5zIGlzIG5vcm1hbCBudW1iZXI/XG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIHhudW1iZXIuaXNOb3JtYWwoMy4xNCk7XG4gKiAvLyDihpIgdHJ1ZVxuICpcbiAqIHhudW1iZXIuaXNOb3JtYWwoMCk7XG4gKiAvLyDihpIgZmFsc2VcbiAqXG4gKiB4bnVtYmVyLmlzTm9ybWFsKDFlLTMyMCk7XG4gKiAvLyDihpIgZmFsc2VcbiAqXG4gKiB4bnVtYmVyLmlzTm9ybWFsKEluZmluaXR5KTtcbiAqIC8vIOKGkiBmYWxzZVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNOb3JtYWwoeDogbnVtYmVyKTogYm9vbGVhbiB7XG4gIGlmICh4ID09PSAwKSByZXR1cm4gZmFsc2U7XG4gIGlmICghTnVtYmVyLmlzRmluaXRlKHgpKSByZXR1cm4gZmFsc2U7XG4gIGlmIChNYXRoLmFicyh4KSA8IE1JTl9OT1JNQUwpIHJldHVybiBmYWxzZTtcbiAgcmV0dXJuIHRydWU7XG59XG5cblxuLyoqXG4gKiBDbGFzc2lmeSBhIG51bWJlciBpbnRvIGl0cyBmbG9hdGluZyBwb2ludCBjYXRlZ29yeS5cbiAqIEBwYXJhbSB4IGEgbnVtYmVyXG4gKiBAcmV0dXJucyBmbG9hdGluZyBwb2ludCBjbGFzcyBvZiBgeGBcbiAqIEBleGFtcGxlXG4gKiBgYGB0c1xuICogeG51bWJlci5jbGFzc2lmeSgwKTtcbiAqIC8vIOKGkiBGbG9hdENsYXNzLlpFUk9cbiAqXG4gKiB4bnVtYmVyLmNsYXNzaWZ5KDFlLTMyMCk7XG4gKiAvLyDihpIgRmxvYXRDbGFzcy5TVUJOT1JNQUxcbiAqXG4gKiB4bnVtYmVyLmNsYXNzaWZ5KDMuMTQpO1xuICogLy8g4oaSIEZsb2F0Q2xhc3MuTk9STUFMXG4gKlxuICogeG51bWJlci5jbGFzc2lmeShJbmZpbml0eSk7XG4gKiAvLyDihpIgRmxvYXRDbGFzcy5JTkZJTklURVxuICpcbiAqIHhudW1iZXIuY2xhc3NpZnkoTmFOKTtcbiAqIC8vIOKGkiBGbG9hdENsYXNzLk5BTlxuICovXG5leHBvcnQgZnVuY3Rpb24gY2xhc3NpZnkoeDogbnVtYmVyKTogRmxvYXRDbGFzcyB7XG4gIGlmICh4ID09PSAwKSAgICAgICAgICAgICAgICAgIHJldHVybiBGbG9hdENsYXNzLlpFUk87XG4gIGlmIChOdW1iZXIuaXNOYU4oeCkpICAgICAgICAgIHJldHVybiBGbG9hdENsYXNzLk5BTjtcbiAgaWYgKCFOdW1iZXIuaXNGaW5pdGUoeCkpICAgICAgcmV0dXJuIEZsb2F0Q2xhc3MuSU5GSU5JVEU7XG4gIGlmIChNYXRoLmFicyh4KSA8IE1JTl9OT1JNQUwpIHJldHVybiBGbG9hdENsYXNzLlNVQk5PUk1BTDtcbiAgcmV0dXJuIEZsb2F0Q2xhc3MuTk9STUFMO1xufVxuXG5cbi8qKlxuICogRXhhbWluZSBpZiBzdW0gb2YgZGl2aXNvcnMgZXF1YWxzIHRoZSBudW1iZXIgaXRzZWxmLlxuICogQHBhcmFtIHggYSBudW1iZXJcbiAqIEByZXR1cm5zIHN1bSBvZiBkaXZpc29ycyh4KSBleGNsdWRpbmcgeCA9IHg/XG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIHhudW1iZXIuaXNQZXJmZWN0KDYpO1xuICogLy8g4oaSIHRydWUgKDErMiszPTYpXG4gKlxuICogeG51bWJlci5pc1BlcmZlY3QoMjgpO1xuICogLy8g4oaSIHRydWUgKDErMis0KzcrMTQ9MjgpXG4gKlxuICogeG51bWJlci5pc1BlcmZlY3QoMTIpO1xuICogLy8g4oaSIGZhbHNlICgxKzIrMys0KzY9MTYpXG4gKlxuICogeG51bWJlci5pc1BlcmZlY3QoMSk7XG4gKiAvLyDihpIgZmFsc2UgKG5vIHByb3BlciBkaXZpc29ycylcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNQZXJmZWN0KHg6IG51bWJlcik6IGJvb2xlYW4ge1xuICByZXR1cm4gYWxpcXVvdFN1bSh4KSA9PT0geDtcbn1cblxuXG4vLyBUT0RPOiBpc0FsbW9zdFBlcmZlY3QoKT9cbi8vIFRPRE86IGlzU2VtaVBlcmZlY3QoKT9cbi8vIFRPRE86IGlzUXVhc2lQZXJmZWN0KCk/XG4vLyBUT0RPOiBpc1dlaXJkKCk/XG5cblxuLyoqXG4gKiBFeGFtaW5lIGlmIHN1bSBvZiBkaXZpc29ycyBleGNlZWRzIHRoZSBudW1iZXIgaXRzZWxmLlxuICogQHBhcmFtIHggYSBudW1iZXJcbiAqIEByZXR1cm5zIHN1bSBvZiBkaXZpc29ycyh4KSBleGNsdWRpbmcgeCA+IHg/XG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIHhudW1iZXIuaXNBYnVuZGFudCg4KTtcbiAqIC8vIOKGkiBmYWxzZSAoMSsyKzQ9NyA8IDgpXG4gKlxuICogeG51bWJlci5pc0FidW5kYW50KDE1KTtcbiAqIC8vIOKGkiBmYWxzZSAoMSszKzU9OSA8IDE1KVxuICpcbiAqIHhudW1iZXIuaXNBYnVuZGFudCgxMik7XG4gKiAvLyDihpIgdHJ1ZSAoMSsyKzMrNCs2PTE2ID4gMTIpXG4gKlxuICogeG51bWJlci5pc0FidW5kYW50KDYpO1xuICogLy8g4oaSIGZhbHNlICgxKzIrMz02ID0gNilcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNBYnVuZGFudCh4OiBudW1iZXIpOiBib29sZWFuIHtcbiAgcmV0dXJuIGFsaXF1b3RTdW0oeCkgPiB4O1xufVxuZXhwb3J0IHtpc0FidW5kYW50IGFzIGlzRXhjZXNzaXZlfTtcblxuXG4vLyBUT0RPOiBpc1ByaW1pdGl2ZUFidW5kYW50KCk/XG4vLyBUT0RPOiBpc1N1cGVyQWJ1bmRhbnQoKT9cblxuXG4vKipcbiAqIE9idGFpbiB0aGUgc3VtIG9mIGRpdmlzb3JzIGV4Y2VlZGluZyB0aGUgbnVtYmVyIGl0c2VsZi5cbiAqIEBwYXJhbSB4IGEgbnVtYmVyXG4gKiBAcmV0dXJucyBzdW0gb2YgZGl2aXNvcnMoeCkgZXhjbHVkaW5nIHggLSB4XG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIHhudW1iZXIuYWJ1bmRhbmNlKDEyKTtcbiAqIC8vIOKGkiA0ICgxKzIrMys0KzY9MTY7IDE2LTEyPTQpXG4gKlxuICogeG51bWJlci5hYnVuZGFuY2UoMTUpO1xuICogLy8g4oaSIC02ICgxKzMrNT05OyA5LTE1PS02KVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhYnVuZGFuY2UoeDogbnVtYmVyKTogbnVtYmVyIHtcbiAgcmV0dXJuIGFsaXF1b3RTdW0oeCkgLSB4O1xufVxuXG5cbi8qKlxuICogT2J0YWluIHRoZSByYXRpbyBvZiBzdW0gb2YgZGl2aXNvcnMgdG8gdGhlIG51bWJlciBpdHNlbGYuXG4gKiBAcGFyYW0geCBhIG51bWJlclxuICogQHJldHVybnMgKHN1bSBvZiBkaXZpc29ycyh4KSkgLyB4XG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIHhudW1iZXIuYWJ1bmRhbmN5SW5kZXgoMTIpO1xuICogLy8g4oaSIDIuMzMzMy4uLiAoMSsyKzMrNCs2KzEyPTI4OyAyOC8xMj03LzMpXG4gKlxuICogeG51bWJlci5hYnVuZGFuY3lJbmRleCgxNSk7XG4gKiAvLyDihpIgMS42ICgxKzMrNSsxNT0yNDsgMjQvMTU9OC81KVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhYnVuZGFuY3lJbmRleCh4OiBudW1iZXIpOiBudW1iZXIge1xuICByZXR1cm4gKGFsaXF1b3RTdW0oeCkgKyB4KSAvIHg7XG59XG5cblxuLy8gVE9ETzogYXJlQW1pY2FibGUoKT9cbi8vIFRPRE86IGFyZUZyaWVuZGx5KCk/XG5cblxuLyoqXG4gKiBDb3VudCB0aGUgbnVtYmVyIG9mIHNpZ25pZmljYW50IGRpZ2l0cyBpbiBhIG51bWJlci5cbiAqIEBwYXJhbSB4IGEgbnVtYmVyXG4gKiBAcmV0dXJucyB8bSAtICcuJ3wgfCB4ID0gbSDDlyAxMOG1iTsgbSA9IG1hbnRpc3NhLCBlID0gZXhwb25lbnRcbiAqIEBleGFtcGxlXG4gKiBgYGB0c1xuICogeG51bWJlci5zaWduaWZpY2FudERpZ2l0cygwLjAwMzQpO1xuICogLy8g4oaSIDJcbiAqXG4gKiB4bnVtYmVyLnNpZ25pZmljYW50RGlnaXRzKDEyMC41ZTUwKTtcbiAqIC8vIOKGkiA0XG4gKlxuICogeG51bWJlci5zaWduaWZpY2FudERpZ2l0cygxMjAuNWUtNTApO1xuICogLy8g4oaSIDRcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gc2lnbmlmaWNhbnREaWdpdHMoeDogbnVtYmVyKTogbnVtYmVyIHtcbiAgY29uc3QgYSA9IHgudG9FeHBvbmVudGlhbCgpO1xuICByZXR1cm4gYS5yZXBsYWNlKC9lW1xcK1xcLTAtOV0qJC8sIFwiXCIpLnJlcGxhY2UoL14wXFwuPzAqfFxcLi8sIFwiXCIpLmxlbmd0aDtcbn1cbi8vIC0gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjI4ODQ3MjAvd2hhdC1pcy10aGUtZmFzdGVzdC13YXktdG8tY291bnQtdGhlLW51bWJlci1vZi1zaWduaWZpY2FudC1kaWdpdHMtb2YtYS1udW1iZXJcbi8vI2VuZHJlZ2lvblxuXG5cblxuXG4vLyNyZWdpb24gQ09NUEFSRVxuLyoqXG4gKiBDb21wYXJlIHR3byBudW1iZXJzLlxuICogQHBhcmFtIHggYSBudW1iZXJcbiAqIEBwYXJhbSB5IGFub3RoZXIgbnVtYmVyXG4gKiBAcmV0dXJucyB4PHk6IC12ZSwgeD15OiAwLCB4Pnk6ICt2ZVxuICogQGV4YW1wbGVcbiAqIGBgYHRzXG4gKiB4bnVtYmVyLmNvbXBhcmUoMTAsIDEyKTtcbiAqIC8vIOKGkiAtMiAgKC12ZSlcbiAqXG4gKiB4bnVtYmVyLmNvbXBhcmUoMTIsIDEyKTtcbiAqIC8vIOKGkiAwXG4gKlxuICogeG51bWJlci5jb21wYXJlKDE3LCAxMik7XG4gKiAvLyDihpIgNSAgKCt2ZSlcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gY29tcGFyZSh4OiBudW1iZXIsIHk6IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiB4IC0geTtcbn1cblxuXG4vKipcbiAqIENoZWNrIGlmIHR3byBudW1iZXJzIGFyZSB1bm9yZGVyZWQgKE5hTiBpbnZvbHZlZCkuXG4gKiBAcGFyYW0geCBhIG51bWJlclxuICogQHBhcmFtIHkgYW5vdGhlciBudW1iZXJcbiAqIEByZXR1cm5zIHg9TmFOIG9yIHk9TmFOP1xuICogQGV4YW1wbGVcbiAqIGBgYHRzXG4gKiB4bnVtYmVyLmlzVW5vcmRlcmVkKDEwLCBOYU4pO1xuICogLy8g4oaSIHRydWVcbiAqXG4gKiB4bnVtYmVyLmlzVW5vcmRlcmVkKE5hTiwgMTIpO1xuICogLy8g4oaSIHRydWVcbiAqXG4gKiB4bnVtYmVyLmlzVW5vcmRlcmVkKDEwLCAxMik7XG4gKiAvLyDihpIgZmFsc2VcbiAqXG4gKiB4bnVtYmVyLmlzVW5vcmRlcmVkKE5hTiwgTmFOKTtcbiAqIC8vIOKGkiB0cnVlXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVW5vcmRlcmVkKHg6IG51bWJlciwgeTogbnVtYmVyKTogYm9vbGVhbiB7XG4gIHJldHVybiBOdW1iZXIuaXNOYU4oeCkgfHwgTnVtYmVyLmlzTmFOKHkpO1xufVxuLy8jZW5kcmVnaW9uXG5cblxuXG5cbi8vI3JlZ2lvbiBTSUdOXG4vKipcbiAqIENvcHkgdGhlIHNpZ24gb2YgYSBudW1iZXIgdG8gYW5vdGhlciBudW1iZXIuXG4gKiBAcGFyYW0gbWFnIG51bWJlciB3aG9zZSBtYWduaXR1ZGUgaXMgdG8gYmUgY29waWVkXG4gKiBAcGFyYW0gc2duIHNpZ24gb2YgdGhlIG51bWJlciB0byBjb3B5XG4gKiBAcmV0dXJucyBgfG1hZ3xgIHdpdGggc2lnbiBvZiBgc2duYFxuICogQGV4YW1wbGVcbiAqIGBgYHRzXG4gKiB4bnVtYmVyLmNvcHlTaWduKDMuMTQsIC0xKTtcbiAqIC8vIOKGkiAtMy4xNFxuICpcbiAqIHhudW1iZXIuY29weVNpZ24oLTMuMTQsIDEpO1xuICogLy8g4oaSIDMuMTRcbiAqXG4gKiB4bnVtYmVyLmNvcHlTaWduKC02LjI4LCAtMSk7XG4gKiAvLyDihpIgLTYuMjhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvcHlTaWduKG1hZzogbnVtYmVyLCBzZ246IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiBNYXRoLnNpZ24oc2duKSA9PT0gTWF0aC5zaWduKG1hZykgPyBtYWcgOiAtbWFnO1xufVxuLy8jZW5kcmVnaW9uXG5cblxuXG5cbi8vI3JlZ2lvbiBST1VORFxuLyoqXG4gKiBSb3VuZCBkb3duIGEgbnVtYmVyIHRvIHNwZWNpZmljIHByZWNpc2lvbi5cbiAqIEBwYXJhbSB4IGEgbnVtYmVyXG4gKiBAcGFyYW0gcHJlIHRvIHByZWNpc2lvbiBbMV1cbiAqIEBleGFtcGxlXG4gKiBgYGB0c1xuICogeG51bWJlci5mbG9vcig5LjE2MSwgMSk7XG4gKiAvLyDihpIgOVxuICpcbiAqIHhudW1iZXIuZmxvb3IoOS4xNjEsIDAuMDEpO1xuICogLy8g4oaSIDkuMTZcbiAqXG4gKiB4bnVtYmVyLmZsb29yKDkuMTYxNywgMC4wNSk7XG4gKiAvLyDihpIgOS4xNVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmbG9vcih4OiBudW1iZXIsIHByZTogbnVtYmVyID0gMSk6IG51bWJlciB7XG4gIHJldHVybiBNYXRoLmZsb29yKHgvcHJlKSAqIHByZTtcbn1cblxuXG4vKipcbiAqIFJvdW5kIHVwIGEgbnVtYmVyIHRvIHNwZWNpZmljIHByZWNpc2lvbi5cbiAqIEBwYXJhbSB4IGEgbnVtYmVyXG4gKiBAcGFyYW0gcHJlIHRvIHByZWNpc2lvbiBbMV1cbiAqIEBleGFtcGxlXG4gKiBgYGB0c1xuICogeG51bWJlci5jZWlsKDkuMTIxLCAxKTtcbiAqIC8vIOKGkiAxMFxuICpcbiAqIHhudW1iZXIuY2VpbCg5LjEyMSwgMC4wMSk7XG4gKiAvLyDihpIgOS4xM1xuICpcbiAqIHhudW1iZXIuY2VpbCg5LjEyMTcsIDAuMDUpO1xuICogLy8g4oaSIDkuMTVcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gY2VpbCh4OiBudW1iZXIsIHByZTogbnVtYmVyID0gMSk6IG51bWJlciB7XG4gIHJldHVybiBNYXRoLmNlaWwoeC9wcmUpICogcHJlO1xufVxuXG5cbi8qKlxuICogUm91bmQgYSBudW1iZXIgdG8gc3BlY2lmaWMgcHJlY2lzaW9uLlxuICogQHBhcmFtIHggYSBudW1iZXJcbiAqIEBwYXJhbSBwcmUgdG8gcHJlY2lzaW9uIFsxXVxuICogQGV4YW1wbGVcbiAqIGBgYHRzXG4gKiB4bnVtYmVyLnJvdW5kKDkuMTM1LCAxKTtcbiAqIC8vIOKGkiA5XG4gKlxuICogeG51bWJlci5yb3VuZCg5LjEzNSwgMWUtMik7XG4gKiAvLyDihpIgOS4xNFxuICpcbiAqIHhudW1iZXIucm91bmQoOS4xMzU3LCAwLjA1KTtcbiAqIC8vIOKGkiA5LjE1XG4gKlxuICogMC4xICsgMC4yXG4gKiAvLyDihpIgMC4zMDAwMDAwMDAwMDAwMDAwNCAod2h5PylcbiAqXG4gKiB4bnVtYmVyLnJvdW5kKDAuMSArIDAuMiwgMWUtMTIpO1xuICogLy8g4oaSIDAuMyAobmljZSEpXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJvdW5kKHg6IG51bWJlciwgcHJlOiBudW1iZXIgPSAxKTogbnVtYmVyIHtcbiAgcmV0dXJuIE1hdGgucm91bmQoeC9wcmUpICogcHJlO1xufVxuXG5cbi8qKlxuICogUGVyZm9ybSBmbG9vci1kaXZpc29uIG9mIHR3byBudW1iZXJzLlxuICogQHBhcmFtIHggZGl2aXNvclxuICogQHBhcmFtIHkgZGl2aWRlbmRcbiAqIEByZXR1cm5zIOKMingveeKMi1xuICogQGV4YW1wbGVcbiAqIGBgYHRzXG4gKiB4bnVtYmVyLmZsb29yRGl2KDE1LCA0KTtcbiAqIC8vIOKGkiAzXG4gKlxuICogeG51bWJlci5mbG9vckRpdigyLCAyKTtcbiAqIC8vIOKGkiAxXG4gKlxuICogeG51bWJlci5mbG9vckRpdigtMTUsIDQpO1xuICogLy8g4oaSIC00XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZsb29yRGl2KHg6IG51bWJlciwgeTogbnVtYmVyKTogbnVtYmVyIHtcbiAgcmV0dXJuIE1hdGguZmxvb3IoeC95KTtcbn1cblxuXG4vKipcbiAqIFBlcmZvcm0gY2VpbGluZy1kaXZpc29uIG9mIHR3byBudW1iZXJzLlxuICogQHBhcmFtIHggZGl2aXNvclxuICogQHBhcmFtIHkgZGl2aWRlbmRcbiAqIEByZXR1cm5zIOKMiHgveeKMiVxuICogQGV4YW1wbGVcbiAqIGBgYHRzXG4gKiB4bnVtYmVyLmNlaWxEaXYoMTUsIDQpO1xuICogLy8g4oaSIDRcbiAqXG4gKiB4bnVtYmVyLmNlaWxEaXYoMiwgMik7XG4gKiAvLyDihpIgMVxuICpcbiAqIHhudW1iZXIuY2VpbERpdigtMTUsIDQpO1xuICogLy8g4oaSIC0zXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNlaWxEaXYoeDogbnVtYmVyLCB5OiBudW1iZXIpOiBudW1iZXIge1xuICByZXR1cm4gTWF0aC5jZWlsKHgveSk7XG59XG5cblxuLyoqXG4gKiBQZXJmb3JtIHJvdW5kZWQtZGl2aXNvbiBvZiB0d28gbnVtYmVycy5cbiAqIEBwYXJhbSB4IGRpdmlzb3JcbiAqIEBwYXJhbSB5IGRpdmlkZW5kXG4gKiBAcmV0dXJucyBbeC95XVxuICogQGV4YW1wbGVcbiAqIGBgYHRzXG4gKiB4bnVtYmVyLnJvdW5kRGl2KDE1LCA0KTtcbiAqIC8vIOKGkiA0XG4gKlxuICogeG51bWJlci5yb3VuZERpdigyLCAyKTtcbiAqIC8vIOKGkiAxXG4gKlxuICogeG51bWJlci5yb3VuZERpdigtMTUsIDQpO1xuICogLy8g4oaSIC00XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJvdW5kRGl2KHg6IG51bWJlciwgeTogbnVtYmVyKTogbnVtYmVyIHtcbiAgcmV0dXJuIE1hdGgucm91bmQoeC95KTtcbn1cbi8vI2VuZHJlZ2lvblxuXG5cblxuXG4vLyNyZWdpb24gTU9EVUxPXG4vKipcbiAqIEZpbmQgdGhlIHJlbWFpbmRlciBvZiB4L3kgd2l0aCBzaWduIG9mIHggKHRydW5jYXRlZCBkaXZpc2lvbikuXG4gKiBAcGFyYW0geCBkaXZpZGVuZFxuICogQHBhcmFtIHkgZGl2aXNvclxuICogQHJldHVybnMgdHJ1bmMoeCAlIHkpXG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIHhudW1iZXIucmVtKDEsIDEwKTtcbiAqIC8vIOKGkiAxXG4gKlxuICogeG51bWJlci5yZW0oLTEsIDEwKTtcbiAqIC8vIOKGkiAtMVxuICpcbiAqIHhudW1iZXIucmVtKDEsIC0xMCk7XG4gKiAvLyDihpIgMVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZW0oeDogbnVtYmVyLCB5OiBudW1iZXIpOiBudW1iZXIge1xuICByZXR1cm4geCAlIHk7XG59XG4vLyAtIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL01vZHVsb19vcGVyYXRpb25cblxuXG4vKipcbiAqIEZpbmQgdGhlIHJlbWFpbmRlciBvZiB4L3kgd2l0aCBzaWduIG9mIHkgKGZsb29yZWQgZGl2aXNpb24pLlxuICogQHBhcmFtIHggZGl2aWRlbmRcbiAqIEBwYXJhbSB5IGRpdmlzb3JcbiAqIEByZXR1cm5zIGZsb29yKHggJSB5KVxuICogQGV4YW1wbGVcbiAqIGBgYHRzXG4gKiB4bnVtYmVyLm1vZCgxLCAxMCk7XG4gKiAvLyDihpIgMVxuICpcbiAqIHhudW1iZXIubW9kKC0xLCAxMCk7XG4gKiAvLyDihpIgOVxuICpcbiAqIHhudW1iZXIubW9kKDEsIC0xMCk7XG4gKiAvLyDihpIgLTlcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gbW9kKHg6IG51bWJlciwgeTogbnVtYmVyKTogbnVtYmVyIHtcbiAgcmV0dXJuIHggLSB5ICogTWF0aC5mbG9vcih4L3kpO1xufVxuLy8gLSBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Nb2R1bG9fb3BlcmF0aW9uXG5cblxuLyoqXG4gKiBGaW5kIHRoZSByZW1haW5kZXIgb2YgeC95IHdpdGggK3ZlIHNpZ24gKGV1Y2xpZGVhbiBkaXZpc2lvbikuXG4gKiBAcGFyYW0geCBkaXZpZGVuZFxuICogQHBhcmFtIHkgZGl2aXNvclxuICogQHJldHVybnMgbj4wOiBmbG9vcih4ICUgeSksIG48MDogY2VpbCh4ICUgeSlcbiAqIEBleGFtcGxlXG4gKiBgYGB0c1xuICogeG51bWJlci5tb2RwKDEsIDEwKTtcbiAqIC8vIOKGkiAxXG4gKlxuICogeG51bWJlci5tb2RwKC0xLCAxMCk7XG4gKiAvLyDihpIgOVxuICpcbiAqIHhudW1iZXIubW9kcCgxLCAtMTApO1xuICogLy8g4oaSIDFcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gbW9kcCh4OiBudW1iZXIsIHk6IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiB4IC0gTWF0aC5hYnMoeSkgKiBNYXRoLmZsb29yKHggLyBNYXRoLmFicyh5KSk7XG59XG4vLyAtIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL01vZHVsb19vcGVyYXRpb25cbi8vI2VuZHJlZ2lvblxuXG5cblxuXG4vLyNyZWdpb24gUkFOR0UgQ09OVFJPTFxuLyoqXG4gKiBDb25zdHJhaW4gYSBudW1iZXIgd2l0aGluIGEgbWluaW11bSBhbmQgYSBtYXhpbXVtIHZhbHVlLlxuICogQHBhcmFtIHggYSBudW1iZXJcbiAqIEBwYXJhbSBtaW4gbWluaW11bSB2YWx1ZVxuICogQHBhcmFtIG1heCBtYXhpbXVtIHZhbHVlXG4gKiBAcmV0dXJucyB4PG1pbjogbWluLCB4Pm1heDogbWF4LCB4XG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIHhudW1iZXIuY29uc3RyYWluKDIwLCAwLCA1MCk7XG4gKiAvLyDihpIgMjBcbiAqXG4gKiB4bnVtYmVyLmNvbnN0cmFpbigtMTAsIDAsIDEwMCk7XG4gKiAvLyDihpIgMFxuICpcbiAqIHhudW1iZXIuY29uc3RyYWluKDEyMCwgMCwgMTAwKTtcbiAqIC8vIOKGkiAxMDBcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gY29uc3RyYWluKHg6IG51bWJlciwgbWluOiBudW1iZXIsIG1heDogbnVtYmVyKTogbnVtYmVyIHtcbiAgcmV0dXJuIE1hdGgubWluKE1hdGgubWF4KHgsIG1pbiksIG1heCk7XG59XG5leHBvcnQge2NvbnN0cmFpbiBhcyBjbGFtcH07XG4vLyAtIGh0dHBzOi8vcHJvY2Vzc2luZy5vcmcvcmVmZXJlbmNlL2NvbnN0cmFpbl8uaHRtbFxuLy8gLSBodHRwczovL3d3dy5ucG1qcy5jb20vcGFja2FnZS9jbGFtcFxuLy8gLSBodHRwczovL2VuLmNwcHJlZmVyZW5jZS5jb20vdy9jcHAvYWxnb3JpdGhtL2NsYW1wXG4vLyAtIGh0dHBzOi8vZGxhbmcub3JnL2xpYnJhcnkvc3RkL2FsZ29yaXRobS9jb21wYXJpc29uL2NsYW1wLmh0bWxcbi8vIC0gaHR0cHM6Ly93d3cucmRvY3VtZW50YXRpb24ub3JnL3BhY2thZ2VzL3Jhc3Rlci92ZXJzaW9ucy8zLjAtMTIvdG9waWNzL2NsYW1wXG4vLyAtIGh0dHBzOi8vZG9jcy5taWNyb3NvZnQuY29tL2VuLXVzL2RvdG5ldC9hcGkvc3lzdGVtLm1hdGguY2xhbXA/dmlldz1uZXRjb3JlLTMuMVxuLy8gLSBodHRwczovL2RvY3MubWljcm9zb2Z0LmNvbS9lbi11cy93aW5kb3dzL3dpbjMyL2RpcmVjdDNkaGxzbC9keC1ncmFwaGljcy1obHNsLWNsYW1wXG4vLyAtIGh0dHBzOi8vd3d3Lmtocm9ub3Mub3JnL3JlZ2lzdHJ5L09wZW5HTC1SZWZwYWdlcy9nbDQvaHRtbC9jbGFtcC54aHRtbFxuLy8gLSBodHRwczovL2RvY3MudW5pdHkzZC5jb20vU2NyaXB0UmVmZXJlbmNlL01hdGhmLkNsYW1wLmh0bWxcbi8vIC0gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ2xhbXBpbmdfKGdyYXBoaWNzKVxuXG5cbi8qKlxuICogTm9ybWFsaXplIGEgbnVtYmVyIGZyb20gaXRzIGN1cnJlbnQgcmFuZ2UgaW50byBhIHZhbHVlIGJldHdlZW4gMCBhbmQgMS5cbiAqIEBwYXJhbSB4IGEgbnVtYmVyXG4gKiBAcGFyYW0gciBsb3dlciBib3VuZCBvZiBjdXJyZW50IHJhbmdlXG4gKiBAcGFyYW0gUiB1cHBlciBib3VuZCBvZiBjdXJyZW50IHJhbmdlXG4gKiBAcmV0dXJucyDiiIggWzAsIDFdXG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIHhudW1iZXIubm9ybWFsaXplKDIwLCAwLCA1MCk7XG4gKiAvLyDihpIgMC40XG4gKlxuICogeG51bWJlci5ub3JtYWxpemUoLTEwLCAwLCAxMDApO1xuICogLy8g4oaSIC0wLjFcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gbm9ybWFsaXplKHg6IG51bWJlciwgcjogbnVtYmVyLCBSOiBudW1iZXIpOiBudW1iZXIge1xuICByZXR1cm4gKHggLSByKSAvIChSIC0gcik7XG59XG5leHBvcnQge25vcm1hbGl6ZSBhcyBub3JtfTtcbi8vIC0gaHR0cHM6Ly9wcm9jZXNzaW5nLm9yZy9yZWZlcmVuY2Uvbm9ybV8uaHRtbFxuXG5cbi8qKlxuICogUmUtbWFwIGEgbnVtYmVyIGZyb20gb25lIHJhbmdlIHRvIGFub3RoZXIuXG4gKiBAcGFyYW0geCBhIG51bWJlclxuICogQHBhcmFtIHIgbG93ZXIgYm91bmQgb2YgY3VycmVudCByYW5nZVxuICogQHBhcmFtIFIgdXBwZXIgYm91bmQgb2YgY3VycmVudCByYW5nZVxuICogQHBhcmFtIHQgbG93ZXIgYm91bmQgb2YgdGFyZ2V0IHJhbmdlXG4gKiBAcGFyYW0gVCB1cHBlciBib3VuZCBvZiB0YXJnZXQgcmFuZ2VcbiAqIEByZXR1cm5zIOKIiCBbeW1pbiwgeW1heF1cbiAqIEBleGFtcGxlXG4gKiBgYGB0c1xuICogeG51bWJlci5yZW1hcCgyNSwgMCwgMTAwLCAwLCAxMzY2KTtcbiAqIC8vIOKGkiAzNDEuNVxuICpcbiAqIHhudW1iZXIucmVtYXAoMTEwLCAwLCAxMDAsIC0yMCwgLTEwKTtcbiAqIC8vIOKGkiAtOVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZW1hcCh4OiBudW1iZXIsIHI6IG51bWJlciwgUjogbnVtYmVyLCB0OiBudW1iZXIsIFQ6IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiB0ICsgKCh4IC0gcikgLyAoUiAtIHIpKSAqIChUIC0gdCk7XG59XG5leHBvcnQge3JlbWFwIGFzIG1hcH07XG4vLyAtIGh0dHBzOi8vcHJvY2Vzc2luZy5vcmcvcmVmZXJlbmNlL21hcF8uaHRtbFxuXG5cbi8qKlxuICogTGluZWFybHkgaW50ZXJwb2xhdGUgYSBudW1iZXIgYmV0d2VlbiB0d28gbnVtYmVycy5cbiAqIEBwYXJhbSB4IHN0YXJ0IG51bWJlclxuICogQHBhcmFtIHkgc3RvcCBudW1iZXJcbiAqIEBwYXJhbSB0IGludGVycG9sYW50IOKIiCBbMCwgMV1cbiAqIEByZXR1cm5zIOKIiCBbeCwgeV1cbiAqIEBleGFtcGxlXG4gKiBgYGB0c1xuICogeG51bWJlci5sZXJwKDgwLCAzMjAsIDAuOCk7XG4gKiAvLyDihpIgMjcyXG4gKlxuICogeG51bWJlci5sZXJwKDgwLCAzMjAsIDAuMjApO1xuICogLy8g4oaSIDEyOFxuICpcbiAqIHhudW1iZXIubGVycCg4MCwgMzIwLCAwLjMyKTtcbiAqIC8vIOKGkiAxNTYuOFxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsZXJwKHg6IG51bWJlciwgeTogbnVtYmVyLCB0OiBudW1iZXIpOiBudW1iZXIge1xuICByZXR1cm4geCArIHQgKiAoeSAtIHgpO1xufVxuLy8gLSBodHRwczovL3Byb2Nlc3Npbmcub3JnL3JlZmVyZW5jZS9sZXJwXy5odG1sXG4vLyAtIGh0dHBzOi8vZG9jcy51bml0eTNkLmNvbS9TY3JpcHRSZWZlcmVuY2UvVmVjdG9yMy5MZXJwLmh0bWxcbi8vI2VuZHJlZ2lvblxuXG5cblxuXG4vLyNyZWdpb24gRlJBQ1RJT05BTFxuLyoqXG4gKiBNYWtlIGEgbnVtYmVyIHB1cmVseSBmcmFjdGlvbmFsLCBieSBzaGlmdGluZyB0aGUgZGVjaW1hbCBwb2ludC5cbiAqIEBwYXJhbSB4IGEgbnVtYmVyXG4gKiBAcGFyYW0gbiBtYXhpbXVtIG51bWJlciBvZiBkaWdpdHMgdG8gc2hpZnQgKC0xOiBhbGwpIFsyMF1cbiAqIEByZXR1cm5zIGZyYWN0aW9uYWwgbnVtYmVyXG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIHhudW1iZXIuZnJhY3Rpb25pemUoMTIzKTtcbiAqIC8vIOKGkiAwLjEyM1xuICpcbiAqIHhudW1iZXIuZnJhY3Rpb25pemUoLTk4NzYsIDMpO1xuICogLy8g4oaSIC0wLjk4OFxuICpcbiAqIHhudW1iZXIuZnJhY3Rpb25pemUoMC4wMDEyMzQsIDMpO1xuICogLy8g4oaSIDAuMDAxXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZyYWN0aW9uaXplKHg6IG51bWJlciwgbjogbnVtYmVyID0gMjApOiBudW1iZXIge1xuICBjb25zdCB4cCAgID0gTWF0aC5hYnMoeCk7XG4gIGNvbnN0IHhkaWcgPSB4cCA8IDE/IDAgOiAxICsgTWF0aC5mbG9vcihNYXRoLmxvZzEwKHhwKSk7XG4gIGlmIChuIDwgMCkgcmV0dXJuIHggKiBNYXRoLnBvdygxMCwgLXhkaWcpO1xuICByZXR1cm4gTWF0aC5yb3VuZCh4ICogTWF0aC5wb3coMTAsIG4gLSB4ZGlnKSkgKiBNYXRoLnBvdygxMCwgLW4pO1xufVxuXG5cbi8qKlxuICogTWFrZSBhIG51bWJlciBwdXJlbHkgaW50ZWdlciwgYnkgc2hpZnRpbmcgdGhlIGRlY2ltYWwgcG9pbnQuXG4gKiBAcGFyYW0geCBhIG51bWJlclxuICogQHBhcmFtIG4gbWF4aW11bSBudW1iZXIgb2YgZGlnaXRzIHRvIHNoaWZ0ICgtMTogYWxsKSBbMjBdXG4gKiBAcmV0dXJucyBpbnRlZ2VyIG51bWJlclxuICogQGV4YW1wbGVcbiAqIGBgYHRzXG4gKiB4bnVtYmVyLmRlZnJhY3Rpb25pemUoMC4xMjMpO1xuICogLy8g4oaSIDEyM1xuICpcbiAqIHhudW1iZXIuZGVmcmFjdGlvbml6ZSgtMC45ODgsIDIpO1xuICogLy8g4oaSIC05OVxuICpcbiAqIHhudW1iZXIuZGVmcmFjdGlvbml6ZSgxMi4zNDUsIDIpO1xuICogLy8g4oaSIDEyMzVcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVmcmFjdGlvbml6ZSh4OiBudW1iZXIsIG46IG51bWJlciA9IDIwKTogbnVtYmVyIHtcbiAgbGV0IHhwID0gTWF0aC5hYnMoeCksIGkgPSAwO1xuICBmb3IgKDsgbjwwIHx8IGk8bjspIHtcbiAgICB4cCAqPSAxMDsgKytpO1xuICAgIGlmICh4cCAlIDEgPT09IDApIGJyZWFrO1xuICB9XG4gIHJldHVybiBNYXRoLnJvdW5kKHggKiBNYXRoLnBvdygxMCwgaSkpO1xufVxuLy8jZW5kcmVnaW9uXG5cblxuXG5cbi8vI3JlZ2lvbiBBUklUSE1FVElDXG4vKipcbiAqIENoZWNrIGlmIGEgbnVtYmVyIGlzIGEgcG93ZXItb2Ytbi5cbiAqIEBwYXJhbSB4IGEgbnVtYmVyXG4gKiBAcGFyYW0gbiBiYXNlXG4gKiBAcmV0dXJucyBu4oGxID0geD8gfCBpID0gK3ZlIGludGVnZXJcbiAqIEBleGFtcGxlXG4gKiBgYGB0c1xuICogeG51bWJlci5pc1BvdygzMiwgMik7XG4gKiAvLyDihpIgdHJ1ZVxuICpcbiAqIHhudW1iZXIuaXNQb3coMzIsIDQpO1xuICogLy8g4oaSIGZhbHNlXG4gKlxuICogeG51bWJlci5pc1Bvdyg2NCwgNCk7XG4gKiAvLyDihpIgdHJ1ZVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1Bvdyh4OiBudW1iZXIsIG46IG51bWJlcik6IGJvb2xlYW4ge1xuICBpZiAobiA9PT0gMCkgcmV0dXJuIHggPT09IDA7XG4gIGNvbnN0IHAgPSBsb2coTWF0aC5hYnMoeCksIE1hdGguYWJzKG4pKTtcbiAgaWYgKHAgIT09IE1hdGguZmxvb3IocCkpIHJldHVybiBmYWxzZTtcbiAgcmV0dXJuIHggPCAwPyAobiA8IDAgJiYgKHAgJiAxKSA9PT0gMSkgOiAobiA+IDAgfHwgKHAgJiAxKSA9PT0gMCk7XG59XG5cblxuLyoqXG4gKiBGaW5kIGxhcmdlc3QgcG93ZXItb2YtbiBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gZ2l2ZW4gbnVtYmVyLlxuICogQHBhcmFtIHggYSBudW1iZXJcbiAqIEBwYXJhbSBuIGJhc2VcbiAqIEByZXR1cm5zIG7igbEgfCBu4oGxIOKJpCB4IGFuZCBu4oGxID4geC9uXG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIHhudW1iZXIucHJldlBvdygzMiwgMik7XG4gKiAvLyDihpIgMzJcbiAqXG4gKiB4bnVtYmVyLnByZXZQb3coMzUsIDIpO1xuICogLy8g4oaSIDMyXG4gKlxuICogeG51bWJlci5wcmV2UG93KDM1LCAzKTtcbiAqIC8vIOKGkiAyN1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcmV2UG93KHg6IG51bWJlciwgbjogbnVtYmVyKTogbnVtYmVyIHtcbiAgaWYgKHggPD0gMSkgcmV0dXJuIDA7XG4gIGNvbnN0IHAgPSBNYXRoLmZsb29yKE1hdGgubG9nKHgpIC8gTWF0aC5sb2cobikpO1xuICByZXR1cm4gTWF0aC5wb3cobiwgcCk7XG59XG5cblxuLyoqXG4gKiBGaW5kIHNtYWxsZXN0IHBvd2VyLW9mLW4gZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIGdpdmVuIG51bWJlci5cbiAqIEBwYXJhbSB4IGEgbnVtYmVyXG4gKiBAcGFyYW0gbiBiYXNlXG4gKiBAcmV0dXJucyBu4oGxIHwgbuKBsSDiiaUgeCBhbmQgbuKBsSA8IG4qeFxuICogQGV4YW1wbGVcbiAqIGBgYHRzXG4gKiB4bnVtYmVyLm5leHRQb3coMzIsIDIpO1xuICogLy8g4oaSIDMyXG4gKlxuICogeG51bWJlci5uZXh0UG93KDI5LCAyKTtcbiAqIC8vIOKGkiAzMlxuICpcbiAqIHhudW1iZXIubmV4dFBvdygyOSwgMyk7XG4gKiAvLyDihpIgODFcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gbmV4dFBvdyh4OiBudW1iZXIsIG46IG51bWJlcik6IG51bWJlciB7XG4gIGlmICh4IDw9IDApIHJldHVybiAxO1xuICBjb25zdCBwID0gTWF0aC5jZWlsKE1hdGgubG9nKHgpIC8gTWF0aC5sb2cobikpO1xuICByZXR1cm4gTWF0aC5wb3cobiwgcCk7XG59XG5cblxuLyoqXG4gKiBGaW5kIHRoZSBudGggcm9vdCBvZiBhIG51bWJlciAo4oG/4oiaKS5cbiAqIEBwYXJhbSB4IGEgbnVtYmVyXG4gKiBAcGFyYW0gbiByb290XG4gKiBAcmV0dXJucyDigb/iiJp4XG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIHhudW1iZXIucm9vdCgyNSwgMik7XG4gKiAvLyDihpIgNVxuICpcbiAqIHhudW1iZXIucm9vdCgtOCwgMyk7XG4gKiAvLyDihpIgLTJcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gcm9vdCh4OiBudW1iZXIsIG46IG51bWJlcik6IG51bWJlciB7XG4gIGlmICgobiAmIDEpID09PSAwKSByZXR1cm4gTWF0aC5wb3coeCwgMS9uKTtcbiAgcmV0dXJuIE1hdGguc2lnbih4KSAqIE1hdGgucG93KE1hdGguYWJzKHgpLCAxL24pO1xufVxuLy8gLSBodHRwczovL2dpdGh1Yi5jb20vYWxhd2F0dGhlL01hdGhMaWIvYmxvYi9tYXN0ZXIvc3JjL0Z1bmN0bi9mdW5jdGlvbnMvcm9vdC50c1xuXG5cbi8qKlxuICogRmluZCB0aGUgbG9nYXJpdGhtIG9mIGEgbnVtYmVyIHdpdGggYSBnaXZlbiBiYXNlLlxuICogQHBhcmFtIHggYSBudW1iZXJcbiAqIEBwYXJhbSBiIGxvZ2FyaXRobSBiYXNlIFtlXVxuICogQHJldHVybnMgbG9nX2IgKHgpXG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIHhudW1iZXIubG9nKE1hdGguRSk7XG4gKiAvLyDihpIgMVxuICpcbiAqIHhudW1iZXIubG9nKDEwKTtcbiAqIC8vIOKGkiAyLjMwMjU4NTA5Mjk5NDA0NlxuICpcbiAqIHhudW1iZXIubG9nKDI0MywgMyk7XG4gKiAvLyDihpIgNVxuICpcbiAqIHhudW1iZXIubG9nKDY0LCAyKTtcbiAqIC8vIOKGkiA2XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxvZyh4OiBudW1iZXIsIGI6IG51bWJlcj1NYXRoLkUpOiBudW1iZXIge1xuICByZXR1cm4gTWF0aC5sb2coeCkgLyBNYXRoLmxvZyhiKTtcbn1cbi8vIC0gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTG9nYXJpdGhtXG4vLyNlbmRyZWdpb25cblxuXG5cblxuLy8jcmVnaW9uIERJVklTT1JTXG4vKipcbiAqIExpc3QgYWxsIGRpdmlzb3JzIG9mIGEgbnVtYmVyLCBleGNlcHQgaXRzZWxmLlxuICogQHBhcmFtIHggYSBudW1iZXJcbiAqIEByZXR1cm5zIHByb3BlciBkaXZpc29ycyAoZmFjdG9ycylcbiAqIEBleGFtcGxlXG4gKiBgYGB0c1xuICogeG51bWJlci5wcm9wZXJEaXZpc29ycyg2KTtcbiAqIC8vIOKGkiBbMSwgMiwgM11cbiAqXG4gKiB4bnVtYmVyLnByb3BlckRpdmlzb3JzKDEpO1xuICogLy8g4oaSIFtdXG4gKlxuICogeG51bWJlci5wcm9wZXJEaXZpc29ycygwKTtcbiAqIC8vIOKGkiBbXVxuICpcbiAqIHhudW1iZXIucHJvcGVyRGl2aXNvcnMoLTI0KTtcbiAqIC8vIOKGkiBbMSwgMiwgMywgNCwgNiwgOCwgMTJdXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByb3BlckRpdmlzb3JzKHg6IG51bWJlcik6IG51bWJlcltdIHtcbiAgY29uc3QgYSA9IFtdOyB4ID0gTWF0aC5hYnMoeCk7XG4gIGZvciAobGV0IGk9MTsgaTx4OyBpKyspXG4gICAgaWYgKHggJSBpID09PSAwKSBhLnB1c2goaSk7XG4gIHJldHVybiBhO1xufVxuZXhwb3J0IHtwcm9wZXJEaXZpc29ycyBhcyBhbGlxdW90UGFydHN9O1xuLy8gLSBodHRwczovL21hdGh3b3JsZC53b2xmcmFtLmNvbS9Qcm9wZXJEaXZpc29yLmh0bWxcbi8vIC0gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRGl2aXNvciNGdXJ0aGVyX25vdGlvbnNfYW5kX2ZhY3RzXG5cblxuLyoqXG4gKiBTdW0gYWxsIHByb3BlciBkaXZpc29ycyBvZiBhIG51bWJlci5cbiAqIEBwYXJhbSB4IGEgbnVtYmVyXG4gKiBAcmV0dXJucyDOo2ThtaIgfCBk4bWiIGlzIGEgZGl2aXNvciBvZiB4IGFuZCDiiaB4XG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIHhudW1iZXIuYWxpcXVvdFN1bSg2KTtcbiAqIC8vIOKGkiA2ICgxKzIrMylcbiAqXG4gKiB4bnVtYmVyLmFsaXF1b3RTdW0oMSk7XG4gKiAvLyDihpIgMFxuICpcbiAqIHhudW1iZXIuYWxpcXVvdFN1bSgwKTtcbiAqIC8vIOKGkiAwXG4gKlxuICogeG51bWJlci5hbGlxdW90U3VtKC0yNCk7XG4gKiAvLyDihpIgMzYgKDErMiszKzQrNis4KzEyKVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhbGlxdW90U3VtKHg6IG51bWJlcik6IG51bWJlciB7XG4gIGxldCBhID0gMDsgeCA9IE1hdGguYWJzKHgpO1xuICBmb3IgKGxldCBpPTA7IGk8eDsgaSsrKVxuICAgIGlmICh4ICUgaSA9PT0gMCkgYSArPSBpO1xuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIEZpbmQgdGhlIGxlYXN0IHByaW1lIG51bWJlciB3aGljaCBkaXZpZGVzIGEgbnVtYmVyLlxuICogQHBhcmFtIHggYSBudW1iZXJcbiAqIEByZXR1cm5zIGxlYXN0IHByaW1lIGZhY3RvclxuICogQGV4YW1wbGVcbiAqIGBgYHRzXG4gKiB4bnVtYmVyLm1pblByaW1lRmFjdG9yKDEpO1xuICogLy8g4oaSIDBcbiAqXG4gKiB4bnVtYmVyLm1pblByaW1lRmFjdG9yKDMpO1xuICogLy8g4oaSIDNcbiAqXG4gKiB4bnVtYmVyLm1pblByaW1lRmFjdG9yKDIxKTtcbiAqIC8vIOKGkiAzXG4gKlxuICogeG51bWJlci5taW5QcmltZUZhY3Rvcig1NSk7XG4gKiAvLyDihpIgNVxuICpcbiAqIHhudW1iZXIubWluUHJpbWVGYWN0b3IoNTMpO1xuICogLy8g4oaSIDUzXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1pblByaW1lRmFjdG9yKHg6IG51bWJlcik6IG51bWJlciB7XG4gIHggPSBNYXRoLmFicyh4KTtcbiAgLy8gMS4gTFBGIG9mIDIsIDMgaXMgdGhlIG51bWJlciBpdHNlbGYuXG4gIGlmICh4IDw9IDEpIHJldHVybiAwO1xuICBpZiAoeCA8PSAzKSByZXR1cm4geDtcbiAgLy8gMi4gTFBGIGZvciBtdWx0aXBsZXMgb2YgMiwgMy5cbiAgaWYgKHggJSAyID09PSAwKSByZXR1cm4gMjtcbiAgaWYgKHggJSAzID09PSAwKSByZXR1cm4gMztcbiAgLy8gMy4gTFBGIGNhbiBiZSA2ay0xIG9yIDZrKzEuXG4gIGZvciAobGV0IGk9NiwgST1NYXRoLnNxcnQoeCkrMTsgaTw9STsgaSs9Nikge1xuICAgIGlmICh4ICUgKGktMSkgPT09IDApIHJldHVybiBpLTE7XG4gICAgaWYgKHggJSAoaSsxKSA9PT0gMCkgcmV0dXJuIGkrMTtcbiAgfVxuICByZXR1cm4geDtcbn1cbmV4cG9ydCB7bWluUHJpbWVGYWN0b3IgYXMgbGVhc3RQcmltZUZhY3Rvcn07XG4vLyAtIGh0dHBzOi8vbWF0aHdvcmxkLndvbGZyYW0uY29tL0xlYXN0UHJpbWVGYWN0b3IuaHRtbFxuXG5cbi8qKlxuICogRmluZCB0aGUgZ3JlYXRlc3QgcHJpbWUgbnVtYmVyIHdoaWNoIGRpdmlkZXMgYSBudW1iZXIuXG4gKiBAcGFyYW0geCBhIG51bWJlclxuICogQHJldHVybnMgZ3JlYXRlc3QgcHJpbWUgZmFjdG9yXG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIHhudW1iZXIubWF4UHJpbWVGYWN0b3IoMSk7XG4gKiAvLyDihpIgMFxuICpcbiAqIHhudW1iZXIubWF4UHJpbWVGYWN0b3IoMyk7XG4gKiAvLyDihpIgM1xuICpcbiAqIHhudW1iZXIubWF4UHJpbWVGYWN0b3IoMjEpO1xuICogLy8g4oaSIDdcbiAqXG4gKiB4bnVtYmVyLm1heFByaW1lRmFjdG9yKDU1KTtcbiAqIC8vIOKGkiAxMVxuICpcbiAqIHhudW1iZXIubWF4UHJpbWVGYWN0b3IoNTMpO1xuICogLy8g4oaSIDUzXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1heFByaW1lRmFjdG9yKHg6IG51bWJlcik6IG51bWJlciB7XG4gIGxldCBhID0gMDsgeCA9IE1hdGguYWJzKHgpO1xuICAvLyAxLiBHUEYgb2YgMiwgMyBpcyB0aGUgbnVtYmVyIGl0c2VsZi5cbiAgaWYgKHggPD0gMSkgcmV0dXJuIDA7XG4gIGlmICh4IDw9IDMpIHJldHVybiB4O1xuICAvLyAyLiBSZW1vdmUgZmFjdG9ycyAyLCAzLlxuICBmb3IgKDsgeCAlIDIgPT09IDA7IGE9MilcbiAgICB4IC89IDI7XG4gIGZvciAoOyB4ICUgMyA9PT0gMDsgYT0zKVxuICAgIHggLz0gMztcbiAgLy8gMy4gUmVtb3ZlIGZhY3RvcnMgNmstMSwgNmsrMS5cbiAgZm9yIChsZXQgaT02LCBJPU1hdGguc3FydCh4KSsxOyB4PjEgJiYgaTw9STsgaSs9Nikge1xuICAgIGZvciAoOyB4ICUgKGktMSkgPT09IDA7IGE9aS0xKVxuICAgICAgeCAvPSBpLTE7XG4gICAgZm9yICg7IHggJSAoaSsxKSA9PT0gMDsgYT1pKzEpXG4gICAgICB4IC89IGkrMTtcbiAgfVxuICBpZiAoeCA8PSAxKSByZXR1cm4gYTtcbiAgcmV0dXJuIHg7XG59XG5leHBvcnQge21heFByaW1lRmFjdG9yIGFzIGdyZWF0ZXN0UHJpbWVGYWN0b3J9O1xuLy8gLSBodHRwczovL21hdGh3b3JsZC53b2xmcmFtLmNvbS9HcmVhdGVzdFByaW1lRmFjdG9yLmh0bWxcbi8vIC0gaHR0cHM6Ly93d3cuZ2Vla3Nmb3JnZWVrcy5vcmcvZmluZC1sYXJnZXN0LXByaW1lLWZhY3Rvci1udW1iZXIvXG5cblxuLyoqXG4gKiBGaW5kIHRoZSBwcmltZSBmYWN0b3JzIG9mIGEgbnVtYmVyLlxuICogQHBhcmFtIHggYSBudW1iZXJcbiAqIEByZXR1cm5zIFtm4oKALCBm4oKBLCAuLi5dIHwgZuG1oiBkaXZpZGVzIHggYW5kIGlzIHByaW1lXG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIHhudW1iZXIucHJpbWVGYWN0b3JzKDEpO1xuICogLy8g4oaSIFtdXG4gKlxuICogeG51bWJlci5wcmltZUZhY3RvcnMoMyk7XG4gKiAvLyDihpIgWzNdXG4gKlxuICogeG51bWJlci5wcmltZUZhY3RvcnMoMjEpO1xuICogLy8g4oaSIFszLCA3XVxuICpcbiAqIHhudW1iZXIucHJpbWVGYWN0b3JzKDU1KTtcbiAqIC8vIOKGkiBbNSwgMTFdXG4gKlxuICogeG51bWJlci5wcmltZUZhY3RvcnMoNTMpO1xuICogLy8g4oaSIFs1M11cbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJpbWVGYWN0b3JzKHg6IG51bWJlcik6IG51bWJlcltdIHtcbiAgY29uc3QgYTogbnVtYmVyW10gPSBbXTsgeCA9IE1hdGguYWJzKHgpO1xuICBpZiAoeCA8PSAxKSByZXR1cm4gW107XG4gIGlmICh4IDw9IDMpIHJldHVybiBbeF07XG4gIC8vIDIuIFRyeSBmYWN0b3JzIDIsIDMuXG4gIHggPSBwdXNoUHJpbWVGYWN0b3JUbyQoYSwgeCwgMik7XG4gIHggPSBwdXNoUHJpbWVGYWN0b3JUbyQoYSwgeCwgMyk7XG4gIC8vIDMuIFRyeSBmYWN0b3JzIDZrLTEsIDZrKzEuXG4gIGZvciAobGV0IGk9NiwgST1NYXRoLnNxcnQoeCkrMTsgeD4xICYmIGk8PUk7IGkrPTYpIHtcbiAgICB4ID0gcHVzaFByaW1lRmFjdG9yVG8kKGEsIHgsIGktMSk7XG4gICAgeCA9IHB1c2hQcmltZUZhY3RvclRvJChhLCB4LCBpKzEpO1xuICB9XG4gIGlmICh4ID4gMSkgYS5wdXNoKHgpO1xuICByZXR1cm4gYTtcbn1cblxuZnVuY3Rpb24gcHVzaFByaW1lRmFjdG9yVG8kKGE6IG51bWJlcltdLCB4OiBudW1iZXIsIGY6IG51bWJlcik6IG51bWJlciB7XG4gIGlmICh4ICUgZiAhPT0gMCkgcmV0dXJuIHg7XG4gIGRvIHtcbiAgICB4IC89IGY7XG4gIH0gd2hpbGUgKHggJSBmID09PSAwKTtcbiAgYS5wdXNoKGYpO1xuICByZXR1cm4geDtcbn1cbi8vIC0gaHR0cHM6Ly93d3cuZ2Vla3Nmb3JnZWVrcy5vcmcvcHJpbWUtZmFjdG9ycy1iaWctbnVtYmVyL1xuLy8gLSBodHRwczovL21hdGh3b3JsZC53b2xmcmFtLmNvbS9QcmltZUZhY3Rvci5odG1sXG5cblxuLyoqXG4gKiBGaW5kIHRoZSBwcmltZSBmYWN0b3JzIGFuZCByZXNwZWN0aXZlIGV4cG9uZW50cyBvZiBhIG51bWJlci5cbiAqIEBwYXJhbSB4IGEgbnVtYmVyXG4gKiBAcmV0dXJucyBbW2bigoAsIGXigoBdLCBbZuKCgSwgZeKCgV0sIC4uLl0gfCBm4bWiIGlzIGEgcHJpbWUgZmFjdG9yIG9mIHggYW5kIGXhtaIgaXMgaXRzIGV4cG9uZW50XG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIHhudW1iZXIucHJpbWVFeHBvbmVudGlhbHMoMSk7XG4gKiAvLyDihpIgW11cbiAqXG4gKiB4bnVtYmVyLnByaW1lRXhwb25lbnRpYWxzKDkpO1xuICogLy8g4oaSIFtbMywgMl1dXG4gKlxuICogeG51bWJlci5wcmltZUV4cG9uZW50aWFscyg2Myk7XG4gKiAvLyDihpIgW1szLCAyXSwgWzcsIDFdXVxuICpcbiAqIHhudW1iZXIucHJpbWVFeHBvbmVudGlhbHMoNjA1KTtcbiAqIC8vIOKGkiBbWzUsIDFdLCBbMTEsIDJdXVxuICpcbiAqIHhudW1iZXIucHJpbWVFeHBvbmVudGlhbHMoNTMpO1xuICogLy8g4oaSIFtbNTMsIDFdXVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcmltZUV4cG9uZW50aWFscyh4OiBudW1iZXIpOiBbbnVtYmVyLCBudW1iZXJdW10ge1xuICBjb25zdCBhOiBbbnVtYmVyLCBudW1iZXJdW10gPSBbXTsgeCA9IE1hdGguYWJzKHgpO1xuICBpZiAoeCA8PSAxKSByZXR1cm4gW107XG4gIGlmICh4IDw9IDMpIHJldHVybiBbW3gsIDFdXTtcbiAgLy8gMi4gVHJ5IGZhY3RvcnMgMiwgMy5cbiAgeCA9IHB1c2hQcmltZUV4cG9uZW50aWFsVG8kKGEsIHgsIDIpO1xuICB4ID0gcHVzaFByaW1lRXhwb25lbnRpYWxUbyQoYSwgeCwgMyk7XG4gIC8vIDMuIFRyeSBmYWN0b3JzIDZrLTEsIDZrKzEuXG4gIGZvciAobGV0IGk9NiwgST1NYXRoLnNxcnQoeCkrMTsgeD4xICYmIGk8PUk7IGkrPTYpIHtcbiAgICB4ID0gcHVzaFByaW1lRXhwb25lbnRpYWxUbyQoYSwgeCwgaS0xKTtcbiAgICB4ID0gcHVzaFByaW1lRXhwb25lbnRpYWxUbyQoYSwgeCwgaSsxKTtcbiAgfVxuICBpZiAoeCA+IDEpIGEucHVzaChbeCwgMV0pO1xuICByZXR1cm4gYTtcbn1cblxuZnVuY3Rpb24gcHVzaFByaW1lRXhwb25lbnRpYWxUbyQoYTogW251bWJlciwgbnVtYmVyXVtdLCB4OiBudW1iZXIsIGY6IG51bWJlcik6IG51bWJlciB7XG4gIGlmICh4ICUgZiAhPT0gMCkgcmV0dXJuIHg7XG4gIGxldCBlID0gMDtcbiAgZG8ge1xuICAgIHggLz0gZjsgKytlO1xuICB9IHdoaWxlICh4ICUgZiA9PT0gMCk7XG4gIGEucHVzaChbZiwgZV0pO1xuICByZXR1cm4geDtcbn1cbi8vIC0gaHR0cHM6Ly93d3cuZ2Vla3Nmb3JnZWVrcy5vcmcvcHJpbWUtZmFjdG9ycy1iaWctbnVtYmVyL1xuLy8gLSBodHRwczovL3JlZmVyZW5jZS53b2xmcmFtLmNvbS9sYW5ndWFnZS9yZWYvRmFjdG9ySW50ZWdlci5odG1sXG4vLyAtIGh0dHBzOi8vbWF0aHdvcmxkLndvbGZyYW0uY29tL1ByaW1lRmFjdG9yaXphdGlvbi5odG1sXG4vLyAtIGh0dHBzOi8vbWF0aHdvcmxkLndvbGZyYW0uY29tL1ByaW1lRmFjdG9yLmh0bWxcblxuXG4vKipcbiAqIEV4YW1pbmUgaWYgbnVtYmVyIGlzIHByaW1lLlxuICogQHBhcmFtIHggYSBudW1iZXJcbiAqIEByZXR1cm5zIGlzIGRpdmlzaWJsZSBieSAxIGFuZCBpdHNlbGYgb25seT9cbiAqIEBleGFtcGxlXG4gKiBgYGB0c1xuICogeG51bWJlci5pc1ByaW1lKDcpO1xuICogLy8g4oaSIHRydWVcbiAqXG4gKiB4bnVtYmVyLmlzUHJpbWUoNTMpO1xuICogLy8g4oaSIHRydWVcbiAqXG4gKiB4bnVtYmVyLmlzUHJpbWUoNCk7XG4gKiAvLyDihpIgZmFsc2VcbiAqXG4gKiB4bnVtYmVyLmlzUHJpbWUoMSk7XG4gKiAvLyDihpIgZmFsc2VcbiAqXG4gKiB4bnVtYmVyLmlzUHJpbWUoMCk7XG4gKiAvLyDihpIgZmFsc2VcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNQcmltZSh4OiBudW1iZXIpOiBib29sZWFuIHtcbiAgcmV0dXJuIHggIT09IDAgJiYgbWluUHJpbWVGYWN0b3IoeCkgPT09IE1hdGguYWJzKHgpO1xufVxuXG5cbi8qKlxuICogRmluZCB0aGUgZ3JlYXRlc3QgY29tbW9uIGRpdmlzb3Igb2YgbnVtYmVycy5cbiAqIEBwYXJhbSB4cyBhIGxpc3Qgb2YgbnVtYmVyc1xuICogQHJldHVybnMgZ2NkKHjigoEsIHjigoIsIC4uLilcbiAqIEBleGFtcGxlXG4gKiBgYGB0c1xuICogeG51bWJlci5nY2QoNiwgMTUpO1xuICogLy8g4oaSIDNcbiAqXG4gKiB4bnVtYmVyLmdjZCg2LCAxNSwgMjEpO1xuICogLy8g4oaSIDNcbiAqXG4gKiB4bnVtYmVyLmdjZCg2LCAxNSwgMjApO1xuICogLy8g4oaSIDFcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2NkKC4uLnhzOiBudW1iZXJbXSk6IG51bWJlciB7XG4gIGxldCBhID0geHNbMF0gfHwgMTtcbiAgZm9yIChsZXQgaT0xLCBJPXhzLmxlbmd0aDsgaTxJOyBpKyspXG4gICAgYSA9IGdjZFBhaXIoYSwgeHNbaV0pO1xuICByZXR1cm4gYTtcbn1cbmV4cG9ydCB7Z2NkIGFzIGhjZn07XG5cbi8vIEZpbmQgdGhlIGdyZWF0ZXN0IGNvbW1vbiBkaXZpc29yIG9mIGEgcGFpciBvZiBudW1iZXJzLlxuZnVuY3Rpb24gZ2NkUGFpcih4OiBudW1iZXIsIHk6IG51bWJlcik6IG51bWJlciB7XG4gIHdoaWxlICh5ICE9PSAwKSB7XG4gICAgY29uc3QgdCA9IHk7XG4gICAgeSA9IHggJSB5O1xuICAgIHggPSB0O1xuICB9XG4gIHJldHVybiB4O1xufVxuLy8gLSBodHRwczovL2xlbWlyZS5tZS9ibG9nLzIwMTMvMTIvMjYvZmFzdGVzdC13YXktdG8tY29tcHV0ZS10aGUtZ3JlYXRlc3QtY29tbW9uLWRpdmlzb3IvXG4vLyAtIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0V1Y2xpZGVhbl9hbGdvcml0aG1cblxuXG4vKipcbiAqIEZpbmQgdGhlIGxlYXN0IGNvbW1vbiBtdWx0aXBsZSBvZiBudW1iZXJzLlxuICogQHBhcmFtIHhzIGEgbGlzdCBvZiBudW1iZXJzXG4gKiBAcmV0dXJucyBsY20oeOKCgSwgeOKCgiwgLi4uKVxuICogQGV4YW1wbGVcbiAqIGBgYHRzXG4gKiB4bnVtYmVyLmxjbSgyLCAzKTtcbiAqIC8vIOKGkiA2XG4gKlxuICogeG51bWJlci5sY20oMiwgMywgNCk7XG4gKiAvLyDihpIgMTJcbiAqXG4gKiB4bnVtYmVyLmxjbSgyLCAzLCA0LCA1KTtcbiAqIC8vIOKGkiA2MFxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsY20oLi4ueHM6IG51bWJlcltdKTogbnVtYmVyIHtcbiAgbGV0IGEgPSB4c1swXSB8fCAxO1xuICBmb3IgKGxldCBpPTEsIEk9eHMubGVuZ3RoOyBpPEk7IGkrKylcbiAgICAgIGEgPSBhKnhzW2ldIC8gZ2NkUGFpcihhLCB4c1tpXSk7XG4gIHJldHVybiBhO1xufVxuLy8gLSBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9MZWFzdF9jb21tb25fbXVsdGlwbGVcbi8vI2VuZHJlZ2lvblxuXG5cblxuXG4vLyNyZWdpb24gQVJSQU5HRU1FTlRTXG4vKipcbiAqIEZpbmQgdGhlIGZhY3RvcmlhbCBvZiBhIG51bWJlci5cbiAqIEBwYXJhbSBuIGEgbnVtYmVyXG4gKiBAcGFyYW0gayBkZW5vbWluYXRvciBmYWN0b3JpYWwgWzBdXG4gKiBAcmV0dXJucyBQKG4sIGspOyBrPTA6IG4hLCBrPjA6IG4hL2shXG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIHhudW1iZXIuZmFjdG9yaWFsKDUpO1xuICogLy8g4oaSIDEyMFxuICpcbiAqIHhudW1iZXIuZmFjdG9yaWFsKDYpO1xuICogLy8g4oaSIDcyMFxuICpcbiAqIHhudW1iZXIuZmFjdG9yaWFsKDcpO1xuICogLy8g4oaSIDUwNDBcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gZmFjdG9yaWFsKG46IG51bWJlciwgazogbnVtYmVyID0gMCk6IG51bWJlciB7XG4gIGlmIChuIDwgMCkgcmV0dXJuIDA7XG4gIGxldCBhID0gMTtcbiAgZm9yIChsZXQgaT1rKzE7IGk8PW47IGkrKylcbiAgICBhICo9IGk7XG4gIHJldHVybiBhO1xufVxuLy8gLSBodHRwczovL2dpdGh1Yi5jb20vYWxhd2F0dGhlL01hdGhMaWIvYmxvYi9tYXN0ZXIvc3JjL0Z1bmN0bi9mdW5jdGlvbnMvZmFjdG9yaWFsLnRzXG4vLyAtIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1Blcm11dGF0aW9uXG5cblxuLyoqXG4gKiBGaW5kIHRoZSBudW1iZXIgb2Ygd2F5cyB0byBjaG9vc2UgayBlbGVtZW50cyBmcm9tIGEgc2V0IG9mIG4gZWxlbWVudHMuXG4gKiBAcGFyYW0gbiBlbGVtZW50cyBpbiBzb3VyY2Ugc2V0XG4gKiBAcGFyYW0gayBlbGVtZW50cyBpbiBjaG9vc2Ugc2V0XG4gKiBAcmV0dXJucyBDKG4sIGspXG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIHhudW1iZXIuYmlub21pYWwoNCwgMSk7XG4gKiAvLyDihpIgNFxuICpcbiAqIHhudW1iZXIuYmlub21pYWwoNCwgMik7XG4gKiAvLyDihpIgNlxuICpcbiAqIHhudW1iZXIuYmlub21pYWwoNCwgMyk7XG4gKiAvLyDihpIgNFxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBiaW5vbWlhbChuOiBudW1iZXIsIGs6IG51bWJlcik6IG51bWJlciB7XG4gIC8vIDEuIEdlbmVyYWxpemF0aW9uIHRvIG5lZ2F0aXZlIGludGVnZXJzXG4gIGlmIChrIDwgMCB8fCBrID4gTWF0aC5hYnMobikpIHJldHVybiAwO1xuICBpZiAobiA8IDApIHJldHVybiBNYXRoLnBvdygtMSwgaykgKiBiaW5vbWlhbCgtbiwgayk7XG4gIC8vIDIuIFRha2UgYWR2YW50YWdlIG9mIHN5bW1ldHJ5XG4gIGsgPSBrID4gbiAtIGs/IG4gLSBrIDogaztcbiAgbGV0IGEgPSAxO1xuICBmb3IgKGxldCBpPTE7IGk8PWs7IGkrKywgbi0tKVxuICAgIGEgKj0gbi9pO1xuICByZXR1cm4gYTtcbn1cbi8vIC0gaHR0cHM6Ly9naXRodWIuY29tL2FsYXdhdHRoZS9NYXRoTGliL2Jsb2IvbWFzdGVyL3NyYy9GdW5jdG4vZnVuY3Rpb25zL2Jpbm9taWFsLnRzXG4vLyAtIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Jpbm9taWFsX2NvZWZmaWNpZW50XG5cblxuLyoqXG4gKiBGaW5kIHRoZSBudW1iZXIgb2Ygd2F5cyB0byBwdXQgbiBvYmplY3RzIGluIG0gYmlucyAobj1zdW0oa+G1oikpLlxuICogQHBhcmFtIGtzIG9iamVjdHMgcGVyIGJpbiAoa+G1oilcbiAqIEByZXR1cm5zIG4hLyhr4oKBIWvigoIhLi4uKSB8IG49c3VtKGvhtaIpXG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIHhudW1iZXIubXVsdGlub21pYWwoMSwgMik7XG4gKiAvLyDihpIgM1xuICpcbiAqIHhudW1iZXIubXVsdGlub21pYWwoMSwgMiwgMyk7XG4gKiAvLyDihpIgNjBcbiAqXG4gKiB4bnVtYmVyLm11bHRpbm9taWFsKDEsIDIsIDMsIDQpO1xuICogLy8g4oaSIDEyNjAwXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG11bHRpbm9taWFsKC4uLmtzOiBudW1iZXJbXSk6IG51bWJlciB7XG4gIGxldCBuID0gc3VtKC4uLmtzKSwgYSA9IDE7XG4gIGZvciAobGV0IGk9MCwgaj0wLCBJPWtzLmxlbmd0aDsgaTxJOykge1xuICAgIGlmIChqIDw9IDApIGogPSBrc1tpKytdO1xuICAgIGVsc2UgYSAqPSBuLS0gLyBqLS07XG4gIH1cbiAgcmV0dXJuIGE7XG59XG4vLyAtIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL011bHRpbm9taWFsX2Rpc3RyaWJ1dGlvblxuLy8jZW5kcmVnaW9uXG5cblxuXG5cbi8vI3JlZ2lvbiBHRU9NRVRSWVxuLyoqXG4gKiBDb252ZXJ0IHJhZGlhbnMgdG8gZGVncmVlcy5cbiAqIEBwYXJhbSB4IHJhZGlhbnNcbiAqIEByZXR1cm5zIDLPgCDihpIgMzYwXG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIHhudW1iZXIuZGVncmVlcygzKTtcbiAqIC8vIOKGkiAxNzEuODg3MzM4NTM5MjQ2OTdcbiAqXG4gKiB4bnVtYmVyLmRlZ3JlZXMoMSk7XG4gKiAvLyDihpIgNTcuMjk1Nzc5NTEzMDgyMzJcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVncmVlcyh4OiBudW1iZXIpOiBudW1iZXIge1xuICByZXR1cm4geCAqICgxODAgLyBNYXRoLlBJKTtcbn1cbi8vIC0gaHR0cHM6Ly9wcm9jZXNzaW5nLm9yZy9yZWZlcmVuY2UvZGVncmVlc18uaHRtbFxuXG5cbi8qKlxuICogQ29udmVydCBkZWdyZWVzIHRvIHJhZGlhbnMuXG4gKiBAcGFyYW0geCBkZWdyZWVzXG4gKiBAcmV0dXJucyAzNjAg4oaSIDLPgFxuICogQGV4YW1wbGVcbiAqIGBgYHRzXG4gKiB4bnVtYmVyLnJhZGlhbnMoMTgwKTtcbiAqIC8vIOKGkiAzLjE0MTU5MjY1MzU4OTc5M1xuICpcbiAqIHhudW1iZXIucmFkaWFucyg2MCk7XG4gKiAvLyDihpIgMS4wNDcxOTc1NTExOTY1OTc2XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJhZGlhbnMoeDogbnVtYmVyKTogbnVtYmVyIHtcbiAgcmV0dXJuIHggKiAoTWF0aC5QSSAvIDE4MCk7XG59XG4vLyAtIGh0dHBzOi8vcHJvY2Vzc2luZy5vcmcvcmVmZXJlbmNlL3JhZGlhbnNfLmh0bWxcbi8vI2VuZHJlZ2lvblxuXG5cblxuXG4vLyNyZWdpb24gU1RBVElTVElDU1xuLyoqXG4gKiBGaW5kIHRoZSBzdW0gb2YgbnVtYmVycyAozqMpLlxuICogQHBhcmFtIHhzIGEgbGlzdCBvZiBudW1iZXJzXG4gKiBAcmV0dXJucyDOo3jhtaJcbiAqIEBleGFtcGxlXG4gKiBgYGB0c1xuICogeG51bWJlci5zdW0oMSwgMik7XG4gKiAvLyDihpIgM1xuICpcbiAqIHhudW1iZXIuc3VtKDEsIDIsIDMpO1xuICogLy8g4oaSIDZcbiAqXG4gKiB4bnVtYmVyLnN1bSgxLCAyLCAzLCA0KTtcbiAqIC8vIOKGkiAxMFxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdW0oLi4ueHM6IG51bWJlcltdKTogbnVtYmVyIHtcbiAgbGV0IGEgPSAwO1xuICBmb3IgKGNvbnN0IHggb2YgeHMpXG4gICAgYSArPSB4O1xuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIEZpbmQgdGhlIHByb2R1Y3Qgb2YgbnVtYmVycyAo4oiPKS5cbiAqIEBwYXJhbSB4cyBhIGxpc3Qgb2YgbnVtYmVyc1xuICogQHJldHVybnMg4oiPeOG1olxuICogQGV4YW1wbGVcbiAqIGBgYHRzXG4gKiB4bnVtYmVyLnByb2R1Y3QoMSwgMik7XG4gKiAvLyDihpIgMlxuICpcbiAqIHhudW1iZXIucHJvZHVjdCgxLCAyLCAzKTtcbiAqIC8vIOKGkiA2XG4gKlxuICogeG51bWJlci5wcm9kdWN0KDEsIDIsIDMsIDQpO1xuICogLy8g4oaSIDI0XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByb2R1Y3QoLi4ueHM6IG51bWJlcltdKTogbnVtYmVyIHtcbiAgbGV0IGEgPSAxO1xuICBmb3IgKGNvbnN0IHggb2YgeHMpXG4gICAgYSAqPSB4O1xuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIEZpbmQgdGhlIHZhbHVlIHNlcGFyYXRpbmcgdGhlIGhpZ2hlciBhbmQgbG93ZXIgaGFsdmVzIG9mIG51bWJlcnMuXG4gKiBAcGFyYW0geHMgYSBsaXN0IG9mIG51bWJlcnNcbiAqIEByZXR1cm5zIHjigpggfCBzb3J0KHhzKSA9IFsuLi4sIHjigpgsIC4uLl1cbiAqIEBleGFtcGxlXG4gKiBgYGB0c1xuICogeG51bWJlci5tZWRpYW4oMSwgNyk7XG4gKiAvLyDihpIgNFxuICpcbiAqIHhudW1iZXIubWVkaWFuKDEsIDcsIDgpO1xuICogLy8g4oaSIDdcbiAqXG4gKiB4bnVtYmVyLm1lZGlhbigxLCA3LCA4LCAxMCk7XG4gKiAvLyDihpIgNy41XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1lZGlhbiguLi54czogbnVtYmVyW10pOiBudW1iZXIge1xuICBpZiAoeHMubGVuZ3RoID09PSAwKSByZXR1cm4gMDtcbiAgeHMuc29ydCgoYSwgYikgPT4gYSAtIGIpO1xuICBjb25zdCBpID0geHMubGVuZ3RoID4+IDE7XG4gIGlmICgoeHMubGVuZ3RoICYgMSkgPT09IDEpIHJldHVybiB4c1tpXTtcbiAgcmV0dXJuICh4c1tpIC0gMV0gKyB4c1tpXSkgLyAyO1xufVxuLy8gLSBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy80NTMwOTQ0Ny9jYWxjdWxhdGluZy1tZWRpYW4tamF2YXNjcmlwdFxuLy8gLSBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9NZWRpYW5cblxuXG4vKipcbiAqIEZpbmQgdGhlIHZhbHVlcyB0aGF0IGFwcGVhciBtb3N0IG9mdGVuLlxuICogQHBhcmFtIHhzIGEgbGlzdCBvZiBudW1iZXJzXG4gKiBAcmV0dXJucyBbeOKCmOKCgSwgeOKCmOKCgiwgLi4uXSB8IGNvdW50KHjigpjhtaIpIOKJpSBjb3VudCh44bWiKSDiiIAgeOG1oiDiiIggeHNcbiAqIEBleGFtcGxlXG4gKiBgYGB0c1xuICogeG51bWJlci5tb2RlcygxLCAyKTtcbiAqIC8vIOKGkiBbMSwgMl1cbiAqXG4gKiB4bnVtYmVyLm1vZGVzKDEsIDIsIDIpO1xuICogLy8g4oaSIFsyXVxuICpcbiAqIHhudW1iZXIubW9kZXMoMSwgMiwgMiwgMywgMyk7XG4gKiAvLyDihpIgWzIsIDNdXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1vZGVzKC4uLnhzOiBudW1iZXJbXSk6IG51bWJlcltdIHtcbiAgeHMuc29ydCgoYSwgYikgPT4gYSAtIGIpO1xuICBjb25zdCByID0gbWF4UmVwZWF0KHhzKTtcbiAgcmV0dXJuIGdldFJlcGVhdHMoeHMsIHIpO1xufVxuLy8gLSBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Nb2RlXyhzdGF0aXN0aWNzKVxuXG4vLyBHZXQgdGhlIG1heGltdW0gbnVtYmVyIG9mIHRpbWVzIGFueSBudW1iZXIgaGFzIHJlcGVhdGVkIGluIGEgc29ydGVkIGFycmF5LlxuZnVuY3Rpb24gbWF4UmVwZWF0KHhzOiBudW1iZXJbXSk6IG51bWJlciB7XG4gIGxldCBjb3VudCA9IE1hdGgubWluKHhzLmxlbmd0aCwgMSksIG1heCA9IGNvdW50O1xuICBmb3IgKGxldCBpPTEsIEk9eHMubGVuZ3RoOyBpPEk7IGkrKykge1xuICAgIGlmICh4c1tpLTFdID09PSB4c1tpXSkgY291bnQrKztcbiAgICBlbHNlIHsgbWF4ID0gTWF0aC5tYXgobWF4LCBjb3VudCk7IGNvdW50ID0gMTsgfVxuICB9XG4gIHJldHVybiBNYXRoLm1heChtYXgsIGNvdW50KTtcbn1cblxuLy8gR2V0IHRoZSBudW1iZXJzIHdoaWNoIGhhdmUgYmVlbiByZXBlYXRlZCBhdGxlYXN0IGdpdmVuIG51bWJlciBvZiB0aW1lcy5cbmZ1bmN0aW9uIGdldFJlcGVhdHMoeHM6IG51bWJlcltdLCByOiBudW1iZXIpOiBudW1iZXJbXSB7XG4gIGNvbnN0IGE6IG51bWJlcltdID0gW107IHItLTtcbiAgZm9yIChsZXQgaT0wLCBJPXhzLmxlbmd0aC1yOyBpPEk7IGkrKylcbiAgICBpZiAoeHNbaV0gPT09IHhzW2krcl0pIGEucHVzaCh4c1tpKz1yXSk7XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogRmluZCB0aGUgc21hbGxlc3QgYW5kIGxhcmdlc3QgdmFsdWVzLlxuICogQHBhcmFtIHhzIGEgbGlzdCBvZiBudW1iZXJzXG4gKiBAcmV0dXJucyBbbWluKHhzKSwgbWF4KHhzKV1cbiAqIEBleGFtcGxlXG4gKiBgYGB0c1xuICogeG51bWJlci5yYW5nZSgxLCA3KTtcbiAqIC8vIOKGkiA2XG4gKlxuICogeG51bWJlci5yYW5nZSgxLCA3LCA2KTtcbiAqIC8vIOKGkiA2XG4gKlxuICogeG51bWJlci5yYW5nZSgxLCA3LCA4LCA2KTtcbiAqIC8vIOKGkiA3XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJhbmdlKC4uLnhzOiBudW1iZXJbXSk6IFtudW1iZXIsIG51bWJlcl0ge1xuICByZXR1cm4gW01hdGgubWluKC4uLnhzKSwgTWF0aC5tYXgoLi4ueHMpXTtcbn1cbi8vIC0gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvUmFuZ2VfKHN0YXRpc3RpY3MpXG5cblxuLyoqXG4gKiBGaW5kIHRoZSBtZWFuIG9mIHNxdWFyZWQgZGV2aWF0aW9uIG9mIG51bWJlcnMgZnJvbSBpdHMgbWVhbi5cbiAqIEBwYXJhbSB4cyBhIGxpc3Qgb2YgbnVtYmVyc1xuICogQHJldHVybnMgz4PCsiA9IEVbKHhzIC0gwrUpwrJdIHwgwrUgPSBtZWFuKHhzKVxuICogQGV4YW1wbGVcbiAqIGBgYHRzXG4gKiB4bnVtYmVyLnZhcmlhbmNlKDEsIDIpO1xuICogLy8g4oaSIDAuMjVcbiAqXG4gKiB4bnVtYmVyLnZhcmlhbmNlKDEsIDIsIDMpO1xuICogLy8g4oaSIDAuNjY2NjY2NjY2NjY2NjY2NlxuICpcbiAqIHhudW1iZXIudmFyaWFuY2UoMSwgMiwgMywgNCk7XG4gKiAvLyDihpIgMS4yNVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YXJpYW5jZSguLi54czogbnVtYmVyW10pOiBudW1iZXIge1xuICBpZiAoeHMubGVuZ3RoID09PSAwKSByZXR1cm4gMDtcbiAgY29uc3QgbSA9IGFyaXRobWV0aWNNZWFuKC4uLnhzKTsgbGV0IGEgPSAwO1xuICBmb3IgKGNvbnN0IHggb2YgeHMpXG4gICAgYSArPSAoeCAtIG0pICoqIDI7XG4gIHJldHVybiBhIC8geHMubGVuZ3RoO1xufVxuLy8gLSBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9WYXJpYW5jZVxuLy8jZW5kcmVnaW9uXG5cblxuXG5cblxuLy8jcmVnaW9uIE1FQU4gKFNUQVRJU1RJQ1MpXG4vKipcbiAqIEZpbmQgdGhlIGF2ZXJhZ2Ugb2YgbnVtYmVycy5cbiAqIEBwYXJhbSB4cyBhIGxpc3Qgb2YgbnVtYmVyc1xuICogQHJldHVybnMgzqN44bWiL24gfCBuID0gc2l6ZSh4cylcbiAqIEBleGFtcGxlXG4gKiBgYGB0c1xuICogeG51bWJlci5hcml0aG1ldGhpY01lYW4oMSwgMik7XG4gKiAvLyDihpIgMS41XG4gKlxuICogeG51bWJlci5hcml0aG1ldGhpY01lYW4oMSwgMiwgMyk7XG4gKiAvLyDihpIgMlxuICpcbiAqIHhudW1iZXIuYXJpdGhtZXRoaWNNZWFuKDEsIDIsIDMsIDQpO1xuICogLy8g4oaSIDIuNVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcml0aG1ldGljTWVhbiguLi54czogbnVtYmVyW10pOiBudW1iZXIge1xuICBpZiAoeHMubGVuZ3RoID09PSAwKSByZXR1cm4gMDtcbiAgcmV0dXJuIHN1bSguLi54cykgLyB4cy5sZW5ndGg7XG59XG5leHBvcnQge2FyaXRobWV0aWNNZWFuIGFzIG1lYW59O1xuXG5cbi8qKlxuICogRmluZCB0aGUgZ2VvbWV0cmljIG1lYW4gb2YgbnVtYmVycy5cbiAqIEBwYXJhbSB4cyBhIGxpc3Qgb2YgbnVtYmVyc1xuICogQHJldHVybnMg4oG/4oiaKOKIj3jhtaIpIHwgbiA9IHNpemUoeHMpXG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIHhudW1iZXIuZ2VvbWV0cmljTWVhbigxLCAyKTtcbiAqIC8vIOKGkiAxLjQxNDIxMzU2MjM3MzA5NTEgIChNYXRoLnNxcnQoMikpXG4gKlxuICogeG51bWJlci5nZW9tZXRyaWNNZWFuKDEsIDIsIDMpO1xuICogLy8g4oaSIDEuODE3MTIwNTkyODMyMTM5NyAgKE1hdGguY2JydCg2KSlcbiAqXG4gKiB4bnVtYmVyLmdlb21ldHJpY01lYW4oMSwgMiwgMywgNCk7XG4gKiAvLyDihpIgMi4yMTMzNjM4Mzk0MDA2NDM0ICAoTWF0aC5wb3coMjQsIDEvNCkpXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdlb21ldHJpY01lYW4oLi4ueHM6IG51bWJlcltdKTogbnVtYmVyIHtcbiAgY29uc3QgbiA9IHhzLmxlbmd0aDtcbiAgcmV0dXJuIHJvb3QocHJvZHVjdCguLi54cyksIG4pO1xufVxuXG5cbi8qKlxuICogRmluZCB0aGUgaGFybW9uaWMgbWVhbiBvZiBudW1iZXJzLlxuICogQHBhcmFtIHhzIGEgbGlzdCBvZiBudW1iZXJzXG4gKiBAcmV0dXJucyBuL86jKDEveOG1oikgfCBuID0gc2l6ZSh4cylcbiAqIEBleGFtcGxlXG4gKiBgYGB0c1xuICogeG51bWJlci5oYXJtb25pY01lYW4oMSwgMik7XG4gKiAvLyDihpIgMS4zMzMzMzMzMzMzMzMzMzMzICAoNC8zKVxuICpcbiAqIHhudW1iZXIuaGFybW9uaWNNZWFuKDEsIDIsIDMpO1xuICogLy8g4oaSIDEuNjM2MzYzNjM2MzYzNjM2NSAgKDE4LzExKVxuICpcbiAqIHhudW1iZXIuaGFybW9uaWNNZWFuKDEsIDIsIDMsIDQpO1xuICogLy8g4oaSIDEuOTIgICg0OC8yNSlcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gaGFybW9uaWNNZWFuKC4uLnhzOiBudW1iZXJbXSk6IG51bWJlciB7XG4gIGNvbnN0IG4gPSB4cy5sZW5ndGg7XG4gIGNvbnN0IHAgPSBwcm9kdWN0KC4uLnhzKTsgbGV0IHEgPSAwO1xuICBmb3IgKGNvbnN0IHggb2YgeHMpXG4gICAgcSArPSBwL3g7XG4gIHJldHVybiBuICogcC9xO1xufVxuXG5cbi8qKlxuICogRmluZCB0aGUgcXVhZHJpYXRpYyBtZWFuIG9mIG51bWJlcnMuXG4gKiBAcGFyYW0geHMgYSBsaXN0IG9mIG51bWJlcnNcbiAqIEByZXR1cm5zIOKImijOo3jhtaLCsikvbiB8IG4gPSBzaXplKHhzKVxuICogQGV4YW1wbGVcbiAqIGBgYHRzXG4gKiB4bnVtYmVyLnF1YWRyaWF0aWNNZWFuKDEsIDIpO1xuICogLy8g4oaSIDEuNTgxMTM4ODMwMDg0MTg5OCAgKE1hdGguc3FydCg1LzIpKVxuICpcbiAqIHhudW1iZXIucXVhZHJpYXRpY01lYW4oMSwgMiwgMyk7XG4gKiAvLyDihpIgMi4xNjAyNDY4OTk0NjkyODcgIChNYXRoLnNxcnQoMTQvMykpXG4gKlxuICogeG51bWJlci5xdWFkcmlhdGljTWVhbigxLCAyLCAzLCA0KTtcbiAqIC8vIOKGkiAyLjczODYxMjc4NzUyNTgzMDYgIChNYXRoLnNxcnQoMzAvNCkpXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHF1YWRyaWF0aWNNZWFuKC4uLnhzOiBudW1iZXJbXSk6IG51bWJlciB7XG4gIGNvbnN0IG4gPSB4cy5sZW5ndGg7IGxldCBhID0gMDtcbiAgZm9yIChjb25zdCB4IG9mIHhzKVxuICAgIGEgKz0geCp4O1xuICByZXR1cm4gTWF0aC5zcXJ0KGEvbik7XG59XG5leHBvcnQge3F1YWRyaWF0aWNNZWFuIGFzIHJvb3RNZWFuU3F1YXJlfTtcblxuXG4vKipcbiAqIEZpbmQgdGhlIGN1YmljIG1lYW4gb2YgbnVtYmVycy5cbiAqIEBwYXJhbSB4cyBhIGxpc3Qgb2YgbnVtYmVyc1xuICogQHJldHVybnMgwrPiiJoozqN44bWiwrMpL24gfCBuID0gc2l6ZSh4cylcbiAqIEBleGFtcGxlXG4gKiBgYGB0c1xuICogeG51bWJlci5jdWJpY01lYW4oMSwgMik7XG4gKiAvLyDihpIgMS42NTA5NjM2MjQ0NDczMTM0ICAoTWF0aC5jYnJ0KDkvMikpXG4gKlxuICogeG51bWJlci5jdWJpY01lYW4oMSwgMiwgMyk7XG4gKiAvLyDihpIgMi4yODk0Mjg0ODUxMDY2NjM3ICAoTWF0aC5jYnJ0KDM2LzMpKVxuICpcbiAqIHhudW1iZXIuY3ViaWNNZWFuKDEsIDIsIDMsIDQpO1xuICogLy8g4oaSIDIuOTI0MDE3NzM4MjEyODY2ICAoTWF0aC5jYnJ0KDEwMC80KSlcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gY3ViaWNNZWFuKC4uLnhzOiBudW1iZXJbXSk6IG51bWJlciB7XG4gIGNvbnN0IG4gPSB4cy5sZW5ndGg7IGxldCBhID0gMDtcbiAgZm9yIChjb25zdCB4IG9mIHhzKVxuICAgIGEgKz0geCoqMztcbiAgcmV0dXJuIE1hdGguY2JydChhL24pO1xufVxuLy8jZW5kcmVnaW9uXG5cblxuXG5cbi8vI3JlZ2lvbiBST01BTiBOVU1FUkFMU1xuLyoqIExpc3Qgb2Ygc3ltYm9scyBpbiB0aGUgUm9tYW4gbnVtZXJhbCBzeXN0ZW0uICovXG5jb25zdCBST01BTl9TWU1CT0xTID0gWydJJywgJ0lWJywgJ1YnLCAnSVgnLCAnWCcsICdYTCcsICdMJywgJ1hDJywgJ0MnLCAnQ0QnLCAnRCcsICdDTScsICdNJ107XG4vKiogUmVzcGVjdGl2ZSB2YWx1ZXMgaW4gdGhlIFJvbWFuIG51bWVyYWwgc3lzdGVtLiAqL1xuY29uc3QgUk9NQU5fVkFMVUVTICA9IFsxLCA0LCA1LCA5LCAxMCwgNDAsIDUwLCA5MCwgMTAwLCA0MDAsIDUwMCwgOTAwLCAxMDAwXTtcbi8qKiBNYXhpbXVtIHBvd2VyLW9mLTEwIHJlcHJlc2VudGFibGUgaW4gUm9tYW4gbnVtZXJhbHMuICovXG5jb25zdCBST01BTl9NQVhfUE9XMTAgPSAzO1xuXG5cbi8qKlxuICogQ29udmVydCByb21hbiBudW1lcmFscyB0byBudW1iZXIuXG4gKiBAcGFyYW0gdHh0IHJvbWFuIG51bWVyYWxzXG4gKiBAcmV0dXJucyBlZy4gWENWIC0+IDk1LCBJVi5WIC0+IDQuNSwgSVhlK0lJIC0+IDkwMFxuICogQGV4YW1wbGVcbiAqIGBgYHRzXG4gKiB4bnVtYmVyLmZyb21Sb21hbk51bWVyYWxzKCdYQ1YnKTtcbiAqIC8vIOKGkiA5NVxuICpcbiAqIHhudW1iZXIuZnJvbVJvbWFuTnVtZXJhbHMoJ0lWLlYnKTtcbiAqIC8vIOKGkiA0LjVcbiAqXG4gKiB4bnVtYmVyLmZyb21Sb21hbk51bWVyYWxzKCdJWGUrSUknKTtcbiAqIC8vIOKGkiA5MDBcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gZnJvbVJvbWFuTnVtZXJhbHModHh0OiBzdHJpbmcpOiBudW1iZXIge1xuICBjb25zdCBtICA9IC9eXFxzKigtP1tcXHNJVlhMQ0RNXSspXFxzKig/OlxcLihbXFxzSVZYTENETV0rKSk/KD86RVstK10oW1xcc0lWWExDRE1dKykpP1xccyokL2kuZXhlYyh0eHQpIHx8IFtdO1xuICBjb25zdCBhaW50ID0gZnJvbVJvbWFuSW50ZWdlcihtWzFdKTtcbiAgY29uc3QgYWZyYyA9IG1bMl0/IGZyb21Sb21hbkludGVnZXIobVsyXSkgOiAwO1xuICBjb25zdCBhZXhwID0gbVszXT8gZnJvbVJvbWFuSW50ZWdlcihtWzNdKSA6IDA7XG4gIHJldHVybiBNYXRoLnNpZ24oYWludCkgKiAoTWF0aC5hYnMoYWludCkgKyBmcmFjdGlvbml6ZShhZnJjKSkgKiBNYXRoLnBvdygxMCwgYWV4cCk7XG59XG5leHBvcnQge2Zyb21Sb21hbk51bWVyYWxzIGFzIGZyb21Sb21hbn07XG5cblxuZnVuY3Rpb24gZnJvbVJvbWFuSW50ZWdlcih0eHQ6IHN0cmluZyk6IG51bWJlciB7XG4gIGxldCAgIHMgPSBST01BTl9TWU1CT0xTLmxlbmd0aCAtIDE7XG4gIGNvbnN0IG4gPSB0eHQuc2VhcmNoKC9eXFxzKi0vKSA+PSAwOyBsZXQgYSA9IDA7XG4gIHR4dCA9IHR4dC5yZXBsYWNlKC9cXFcvZywgJycpLnRvVXBwZXJDYXNlKCk7XG4gIGZvciAobGV0IGk9MCwgST10eHQubGVuZ3RoOyBpPEk7ICBpICs9IFJPTUFOX1NZTUJPTFNbc10ubGVuZ3RoKSB7XG4gICAgd2hpbGUgKHMgPj0gMCAmJiB0eHQuc3Vic3RyaW5nKGksIGkgKyAgUk9NQU5fU1lNQk9MU1tzXS5sZW5ndGgpICE9PSBST01BTl9TWU1CT0xTW3NdKSAtLXM7XG4gICAgaWYgKHMgPCAwKSBicmVhaztcbiAgICBhICs9IFJPTUFOX1ZBTFVFU1tzXTtcbiAgfVxuICByZXR1cm4gbj8gLWEgOiBhO1xufVxuXG5cbi8qKlxuICogQ29udmVydCBudW1iZXIgdG8gcm9tYW4gbnVtZXJhbHMuXG4gKiBAcGFyYW0geCBhIG51bWJlclxuICogQHBhcmFtIGV4cCB1c2UgZXhwb25lbnRpYWwvc2NpZW50aWZpYyBub3RhdGlvbiBbZmFsc2VdXG4gKiBAcmV0dXJucyBlZy4gOTUgLT4gWENWLCA0LjUgLT4gSVYuViwgOTAwIC0+IElYZStJSSAoc2NpZW50aWZpYyA9IHRydWUpXG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIHhudW1iZXIudG9Sb21hbk51bWVyYWxzKDk1KTtcbiAqIC8vIOKGkiAnWENWJ1xuICpcbiAqIHhudW1iZXIudG9Sb21hbk51bWVyYWxzKDQuNSk7XG4gKiAvLyDihpIgJ0lWLlYnXG4gKlxuICogeG51bWJlci50b1JvbWFuTnVtZXJhbHMoOTAwLCB0cnVlKTtcbiAqIC8vIOKGkiAnSVhlK0lJJ1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b1JvbWFuTnVtZXJhbHMoeDogbnVtYmVyLCBleHA6IGJvb2xlYW4gPSBmYWxzZSk6IHN0cmluZyB7XG4gIGNvbnN0IHhwID0gTWF0aC5hYnMoeCk7XG4gIC8vIExldCdzIGdldCB0aGUgZXhwb25lbnQgYW5kIG1hbnRpc3NhLlxuICBjb25zdCB4ZXhwID0gTWF0aC5mbG9vcihNYXRoLmxvZzEwKHhwKSk7XG4gIGNvbnN0IGRleHAgPSBleHAgfHwgKHhleHAgPiBST01BTl9NQVhfUE9XMTApPyB4ZXhwIDogMDtcbiAgY29uc3QgZG1hbiA9IHhwICogTWF0aC5wb3coMTAsIC1kZXhwKTtcbiAgY29uc3QgZGZyYyA9IGRlZnJhY3Rpb25pemUoZG1hbiAlIDEsIFJPTUFOX01BWF9QT1cxMCk7XG4gIGNvbnN0IGRpbnQgPSBNYXRoLnNpZ24oeCkgKiBNYXRoLmZsb29yKGRtYW4pO1xuICAvLyBOb3csIGNvbnZlcnQgdG8gcm9tYW4gbnVtZXJhbHMuXG4gIGNvbnN0IGFtYW4gPSB0b1JvbWFuSW50ZWdlcihkaW50KSArIChkZnJjPyAnLicgKyB0b1JvbWFuSW50ZWdlcihkZnJjKSA6ICcnKTtcbiAgY29uc3QgYWV4cCA9IGRleHAgIT09IDA/ICdlJyArIChkZXhwID4gMD8gJysnIDogJycpICsgdG9Sb21hbkludGVnZXIoZGV4cCkgOiAnJztcbiAgcmV0dXJuIGFtYW4gKyBhZXhwO1xufVxuZXhwb3J0IHt0b1JvbWFuTnVtZXJhbHMgYXMgdG9Sb21hbn07XG5cblxuZXhwb3J0IGZ1bmN0aW9uIHRvUm9tYW5JbnRlZ2VyKHg6IG51bWJlcik6IHN0cmluZyB7XG4gIGxldCBhID0geCA8IDA/ICctJyA6ICcnO1xuICB4ID0gTWF0aC5hYnMoeCk7XG4gIGZvciAobGV0IHM9Uk9NQU5fU1lNQk9MUy5sZW5ndGgtMTsgcz49MDsgLS1zKVxuICAgIHdoaWxlICh4ID49IFJPTUFOX1ZBTFVFU1tzXSkge1xuICAgICAgeCAtPSBST01BTl9WQUxVRVNbc107XG4gICAgICBhICs9IFJPTUFOX1NZTUJPTFNbc107XG4gICAgfVxuICByZXR1cm4gYTtcbn1cbi8vI2VuZHJlZ2lvblxuXG5cbi8vIGV4cG9ydCB7ZGVmYXVsdCBhcyBmcm9tU2NpZW50aWZpY30gZnJvbSAnLi9fZnJvbVNjaWVudGlmaWMnO1xuLy8gZXhwb3J0IHtkZWZhdWx0IGFzIHRvU2NpZW50aWZpY30gZnJvbSAnLi9fdG9TY2llbnRpZmljJztcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdz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