Skip to content

Instantly share code, notes, and snippets.

@kentkost
Forked from mahasak/postman-bigint.js
Created December 3, 2020 12:43
Show Gist options
  • Save kentkost/f2699eb1dd41e2eb6203f0d0c77a987e to your computer and use it in GitHub Desktop.
Save kentkost/f2699eb1dd41e2eb6203f0d0c77a987e to your computer and use it in GitHub Desktop.
Postman Test Runner BigInt fix
var BigNumber,
isNumeric = /^-?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,
mathceil = Math.ceil,
mathfloor = Math.floor,
notBool = ' not a boolean or binary digit',
roundingMode = 'rounding mode',
tooManyDigits = 'number type has more than 15 significant digits',
ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_',
BASE = 1e14,
LOG_BASE = 14,
MAX_SAFE_INTEGER = 0x1fffffffffffff, // 2^53 - 1
// MAX_INT32 = 0x7fffffff, // 2^31 - 1
POWS_TEN = [1, 10, 100, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13],
SQRT_BASE = 1e7,
/*
* The limit on the value of DECIMAL_PLACES, TO_EXP_NEG, TO_EXP_POS, MIN_EXP, MAX_EXP, and
* the arguments to toExponential, toFixed, toFormat, and toPrecision, beyond which an
* exception is thrown (if ERRORS is true).
*/
MAX = 1E9; // 0 to MAX_INT32
/*
* Create and return a BigNumber constructor.
*/
function constructorFactory(config) {
var div, parseNumeric,
// id tracks the caller function, so its name can be included in error messages.
id = 0,
P = BigNumber.prototype,
ONE = new BigNumber(1),
/********************************* EDITABLE DEFAULTS **********************************/
/*
* The default values below must be integers within the inclusive ranges stated.
* The values can also be changed at run-time using BigNumber.config.
*/
// The maximum number of decimal places for operations involving division.
DECIMAL_PLACES = 20, // 0 to MAX
/*
* The rounding mode used when rounding to the above decimal places, and when using
* toExponential, toFixed, toFormat and toPrecision, and round (default value).
* UP 0 Away from zero.
* DOWN 1 Towards zero.
* CEIL 2 Towards +Infinity.
* FLOOR 3 Towards -Infinity.
* HALF_UP 4 Towards nearest neighbour. If equidistant, up.
* HALF_DOWN 5 Towards nearest neighbour. If equidistant, down.
* HALF_EVEN 6 Towards nearest neighbour. If equidistant, towards even neighbour.
* HALF_CEIL 7 Towards nearest neighbour. If equidistant, towards +Infinity.
* HALF_FLOOR 8 Towards nearest neighbour. If equidistant, towards -Infinity.
*/
ROUNDING_MODE = 4, // 0 to 8
// EXPONENTIAL_AT : [TO_EXP_NEG , TO_EXP_POS]
// The exponent value at and beneath which toString returns exponential notation.
// Number type: -7
TO_EXP_NEG = -7, // 0 to -MAX
// The exponent value at and above which toString returns exponential notation.
// Number type: 21
TO_EXP_POS = 21, // 0 to MAX
// RANGE : [MIN_EXP, MAX_EXP]
// The minimum exponent value, beneath which underflow to zero occurs.
// Number type: -324 (5e-324)
MIN_EXP = -1e7, // -1 to -MAX
// The maximum exponent value, above which overflow to Infinity occurs.
// Number type: 308 (1.7976931348623157e+308)
// For MAX_EXP > 1e7, e.g. new BigNumber('1e100000000').plus(1) may be slow.
MAX_EXP = 1e7, // 1 to MAX
// Whether BigNumber Errors are ever thrown.
ERRORS = true, // true or false
// Change to intValidatorNoErrors if ERRORS is false.
isValidInt = intValidatorWithErrors, // intValidatorWithErrors/intValidatorNoErrors
// Whether to use cryptographically-secure random number generation, if available.
CRYPTO = false, // true or false
/*
* The modulo mode used when calculating the modulus: a mod n.
* The quotient (q = a / n) is calculated according to the corresponding rounding mode.
* The remainder (r) is calculated as: r = a - n * q.
*
* UP 0 The remainder is positive if the dividend is negative, else is negative.
* DOWN 1 The remainder has the same sign as the dividend.
* This modulo mode is commonly known as 'truncated division' and is
* equivalent to (a % n) in JavaScript.
* FLOOR 3 The remainder has the same sign as the divisor (Python %).
* HALF_EVEN 6 This modulo mode implements the IEEE 754 remainder function.
* EUCLID 9 Euclidian division. q = sign(n) * floor(a / abs(n)).
* The remainder is always positive.
*
* The truncated division, floored division, Euclidian division and IEEE 754 remainder
* modes are commonly used for the modulus operation.
* Although the other rounding modes can also be used, they may not give useful results.
*/
MODULO_MODE = 1, // 0 to 9
// The maximum number of significant digits of the result of the toPower operation.
// If POW_PRECISION is 0, there will be unlimited significant digits.
POW_PRECISION = 0, // 0 to MAX
// The format specification used by the BigNumber.prototype.toFormat method.
FORMAT = {
decimalSeparator: '.',
groupSeparator: ',',
groupSize: 3,
secondaryGroupSize: 0,
fractionGroupSeparator: '\xA0', // non-breaking space
fractionGroupSize: 0
};
/******************************************************************************************/
// CONSTRUCTOR
/*
* The BigNumber constructor and exported function.
* Create and return a new instance of a BigNumber object.
*
* n {number|string|BigNumber} A numeric value.
* [b] {number} The base of n. Integer, 2 to 64 inclusive.
*/
function BigNumber(n, b) {
var c, e, i, num, len, str,
x = this;
// Enable constructor usage without new.
if (!(x instanceof BigNumber)) {
// 'BigNumber() constructor call without new: {n}'
if (ERRORS) raise(26, 'constructor call without new', n);
return new BigNumber(n, b);
}
// 'new BigNumber() base not an integer: {b}'
// 'new BigNumber() base out of range: {b}'
if (b == null || !isValidInt(b, 2, 64, id, 'base')) {
// Duplicate.
if (n instanceof BigNumber) {
x.s = n.s;
x.e = n.e;
x.c = (n = n.c) ? n.slice() : n;
id = 0;
return;
}
if ((num = typeof n == 'number') && n * 0 == 0) {
x.s = 1 / n < 0 ? (n = -n, -1) : 1;
// Fast path for integers.
if (n === ~~n) {
for (e = 0, i = n; i >= 10; i /= 10, e++);
x.e = e;
x.c = [n];
id = 0;
return;
}
str = n + '';
} else {
if (!isNumeric.test(str = n + '')) return parseNumeric(x, str, num);
x.s = str.charCodeAt(0) === 45 ? (str = str.slice(1), -1) : 1;
}
} else {
b = b | 0;
str = n + '';
// Ensure return value is rounded to DECIMAL_PLACES as with other bases.
// Allow exponential notation to be used with base 10 argument.
if (b == 10) {
x = new BigNumber(n instanceof BigNumber ? n : str);
return round(x, DECIMAL_PLACES + x.e + 1, ROUNDING_MODE);
}
// Avoid potential interpretation of Infinity and NaN as base 44+ values.
// Any number in exponential form will fail due to the [Ee][+-].
if ((num = typeof n == 'number') && n * 0 != 0 ||
!(new RegExp('^-?' + (c = '[' + ALPHABET.slice(0, b) + ']+') +
'(?:\\.' + c + ')?$', b < 37 ? 'i' : '')).test(str)) {
return parseNumeric(x, str, num, b);
}
if (num) {
x.s = 1 / n < 0 ? (str = str.slice(1), -1) : 1;
if (ERRORS && str.replace(/^0\.0*|\./, '').length > 15) {
// 'new BigNumber() number type has more than 15 significant digits: {n}'
raise(id, tooManyDigits, n);
}
// Prevent later check for length on converted number.
num = false;
} else {
x.s = str.charCodeAt(0) === 45 ? (str = str.slice(1), -1) : 1;
}
str = convertBase(str, 10, b, x.s);
}
// Decimal point?
if ((e = str.indexOf('.')) > -1) str = str.replace('.', '');
// Exponential form?
if ((i = str.search(/e/i)) > 0) {
// Determine exponent.
if (e < 0) e = i;
e += +str.slice(i + 1);
str = str.substring(0, i);
} else if (e < 0) {
// Integer.
e = str.length;
}
// Determine leading zeros.
for (i = 0; str.charCodeAt(i) === 48; i++);
// Determine trailing zeros.
for (len = str.length; str.charCodeAt(--len) === 48;);
str = str.slice(i, len + 1);
if (str) {
len = str.length;
// Disallow numbers with over 15 significant digits if number type.
// 'new BigNumber() number type has more than 15 significant digits: {n}'
if (num && ERRORS && len > 15 && (n > MAX_SAFE_INTEGER || n !== mathfloor(n))) {
raise(id, tooManyDigits, x.s * n);
}
e = e - i - 1;
// Overflow?
if (e > MAX_EXP) {
// Infinity.
x.c = x.e = null;
// Underflow?
} else if (e < MIN_EXP) {
// Zero.
x.c = [x.e = 0];
} else {
x.e = e;
x.c = [];
// Transform base
// e is the base 10 exponent.
// i is where to slice str to get the first element of the coefficient array.
i = (e + 1) % LOG_BASE;
if (e < 0) i += LOG_BASE;
if (i < len) {
if (i) x.c.push(+str.slice(0, i));
for (len -= LOG_BASE; i < len;) {
x.c.push(+str.slice(i, i += LOG_BASE));
}
str = str.slice(i);
i = LOG_BASE - str.length;
} else {
i -= len;
}
for (; i--; str += '0');
x.c.push(+str);
}
} else {
// Zero.
x.c = [x.e = 0];
}
id = 0;
}
// CONSTRUCTOR PROPERTIES
BigNumber.another = constructorFactory;
BigNumber.ROUND_UP = 0;
BigNumber.ROUND_DOWN = 1;
BigNumber.ROUND_CEIL = 2;
BigNumber.ROUND_FLOOR = 3;
BigNumber.ROUND_HALF_UP = 4;
BigNumber.ROUND_HALF_DOWN = 5;
BigNumber.ROUND_HALF_EVEN = 6;
BigNumber.ROUND_HALF_CEIL = 7;
BigNumber.ROUND_HALF_FLOOR = 8;
BigNumber.EUCLID = 9;
/*
* Configure infrequently-changing library-wide settings.
*
* Accept an object or an argument list, with one or many of the following properties or
* parameters respectively:
*
* DECIMAL_PLACES {number} Integer, 0 to MAX inclusive
* ROUNDING_MODE {number} Integer, 0 to 8 inclusive
* EXPONENTIAL_AT {number|number[]} Integer, -MAX to MAX inclusive or
* [integer -MAX to 0 incl., 0 to MAX incl.]
* RANGE {number|number[]} Non-zero integer, -MAX to MAX inclusive or
* [integer -MAX to -1 incl., integer 1 to MAX incl.]
* ERRORS {boolean|number} true, false, 1 or 0
* CRYPTO {boolean|number} true, false, 1 or 0
* MODULO_MODE {number} 0 to 9 inclusive
* POW_PRECISION {number} 0 to MAX inclusive
* FORMAT {object} See BigNumber.prototype.toFormat
* decimalSeparator {string}
* groupSeparator {string}
* groupSize {number}
* secondaryGroupSize {number}
* fractionGroupSeparator {string}
* fractionGroupSize {number}
*
* (The values assigned to the above FORMAT object properties are not checked for validity.)
*
* E.g.
* BigNumber.config(20, 4) is equivalent to
* BigNumber.config({ DECIMAL_PLACES : 20, ROUNDING_MODE : 4 })
*
* Ignore properties/parameters set to null or undefined.
* Return an object with the properties current values.
*/
BigNumber.config = BigNumber.set = function () {
var v, p,
i = 0,
r = {},
a = arguments,
o = a[0],
has = o && typeof o == 'object' ?
function () {
if (o.hasOwnProperty(p)) return (v = o[p]) != null;
} :
function () {
if (a.length > i) return (v = a[i++]) != null;
};
// DECIMAL_PLACES {number} Integer, 0 to MAX inclusive.
// 'config() DECIMAL_PLACES not an integer: {v}'
// 'config() DECIMAL_PLACES out of range: {v}'
if (has(p = 'DECIMAL_PLACES') && isValidInt(v, 0, MAX, 2, p)) {
DECIMAL_PLACES = v | 0;
}
r[p] = DECIMAL_PLACES;
// ROUNDING_MODE {number} Integer, 0 to 8 inclusive.
// 'config() ROUNDING_MODE not an integer: {v}'
// 'config() ROUNDING_MODE out of range: {v}'
if (has(p = 'ROUNDING_MODE') && isValidInt(v, 0, 8, 2, p)) {
ROUNDING_MODE = v | 0;
}
r[p] = ROUNDING_MODE;
// EXPONENTIAL_AT {number|number[]}
// Integer, -MAX to MAX inclusive or [integer -MAX to 0 inclusive, 0 to MAX inclusive].
// 'config() EXPONENTIAL_AT not an integer: {v}'
// 'config() EXPONENTIAL_AT out of range: {v}'
if (has(p = 'EXPONENTIAL_AT')) {
if (isArray(v)) {
if (isValidInt(v[0], -MAX, 0, 2, p) && isValidInt(v[1], 0, MAX, 2, p)) {
TO_EXP_NEG = v[0] | 0;
TO_EXP_POS = v[1] | 0;
}
} else if (isValidInt(v, -MAX, MAX, 2, p)) {
TO_EXP_NEG = -(TO_EXP_POS = (v < 0 ? -v : v) | 0);
}
}
r[p] = [TO_EXP_NEG, TO_EXP_POS];
// RANGE {number|number[]} Non-zero integer, -MAX to MAX inclusive or
// [integer -MAX to -1 inclusive, integer 1 to MAX inclusive].
// 'config() RANGE not an integer: {v}'
// 'config() RANGE cannot be zero: {v}'
// 'config() RANGE out of range: {v}'
if (has(p = 'RANGE')) {
if (isArray(v)) {
if (isValidInt(v[0], -MAX, -1, 2, p) && isValidInt(v[1], 1, MAX, 2, p)) {
MIN_EXP = v[0] | 0;
MAX_EXP = v[1] | 0;
}
} else if (isValidInt(v, -MAX, MAX, 2, p)) {
if (v | 0) MIN_EXP = -(MAX_EXP = (v < 0 ? -v : v) | 0);
else if (ERRORS) raise(2, p + ' cannot be zero', v);
}
}
r[p] = [MIN_EXP, MAX_EXP];
// ERRORS {boolean|number} true, false, 1 or 0.
// 'config() ERRORS not a boolean or binary digit: {v}'
if (has(p = 'ERRORS')) {
if (v === !!v || v === 1 || v === 0) {
id = 0;
isValidInt = (ERRORS = !!v) ? intValidatorWithErrors : intValidatorNoErrors;
} else if (ERRORS) {
raise(2, p + notBool, v);
}
}
r[p] = ERRORS;
// CRYPTO {boolean|number} true, false, 1 or 0.
// 'config() CRYPTO not a boolean or binary digit: {v}'
// 'config() crypto unavailable: {crypto}'
if (has(p = 'CRYPTO')) {
if (v === true || v === false || v === 1 || v === 0) {
if (v) {
v = typeof crypto == 'undefined';
if (!v && crypto && (crypto.getRandomValues || crypto.randomBytes)) {
CRYPTO = true;
} else if (ERRORS) {
raise(2, 'crypto unavailable', v ? void 0 : crypto);
} else {
CRYPTO = false;
}
} else {
CRYPTO = false;
}
} else if (ERRORS) {
raise(2, p + notBool, v);
}
}
r[p] = CRYPTO;
// MODULO_MODE {number} Integer, 0 to 9 inclusive.
// 'config() MODULO_MODE not an integer: {v}'
// 'config() MODULO_MODE out of range: {v}'
if (has(p = 'MODULO_MODE') && isValidInt(v, 0, 9, 2, p)) {
MODULO_MODE = v | 0;
}
r[p] = MODULO_MODE;
// POW_PRECISION {number} Integer, 0 to MAX inclusive.
// 'config() POW_PRECISION not an integer: {v}'
// 'config() POW_PRECISION out of range: {v}'
if (has(p = 'POW_PRECISION') && isValidInt(v, 0, MAX, 2, p)) {
POW_PRECISION = v | 0;
}
r[p] = POW_PRECISION;
// FORMAT {object}
// 'config() FORMAT not an object: {v}'
if (has(p = 'FORMAT')) {
if (typeof v == 'object') {
FORMAT = v;
} else if (ERRORS) {
raise(2, p + ' not an object', v);
}
}
r[p] = FORMAT;
return r;
};
/*
* Return a new BigNumber whose value is the maximum of the arguments.
*
* arguments {number|string|BigNumber}
*/
BigNumber.max = function () {
return maxOrMin(arguments, P.lt);
};
/*
* Return a new BigNumber whose value is the minimum of the arguments.
*
* arguments {number|string|BigNumber}
*/
BigNumber.min = function () {
return maxOrMin(arguments, P.gt);
};
/*
* Return a new BigNumber with a random value equal to or greater than 0 and less than 1,
* and with dp, or DECIMAL_PLACES if dp is omitted, decimal places (or less if trailing
* zeros are produced).
*
* [dp] {number} Decimal places. Integer, 0 to MAX inclusive.
*
* 'random() decimal places not an integer: {dp}'
* 'random() decimal places out of range: {dp}'
* 'random() crypto unavailable: {crypto}'
*/
BigNumber.random = (function () {
var pow2_53 = 0x20000000000000;
// Return a 53 bit integer n, where 0 <= n < 9007199254740992.
// Check if Math.random() produces more than 32 bits of randomness.
// If it does, assume at least 53 bits are produced, otherwise assume at least 30 bits.
// 0x40000000 is 2^30, 0x800000 is 2^23, 0x1fffff is 2^21 - 1.
var random53bitInt = (Math.random() * pow2_53) & 0x1fffff ?
function () {
return mathfloor(Math.random() * pow2_53);
} :
function () {
return ((Math.random() * 0x40000000 | 0) * 0x800000) +
(Math.random() * 0x800000 | 0);
};
return function (dp) {
var a, b, e, k, v,
i = 0,
c = [],
rand = new BigNumber(ONE);
dp = dp == null || !isValidInt(dp, 0, MAX, 14) ? DECIMAL_PLACES : dp | 0;
k = mathceil(dp / LOG_BASE);
if (CRYPTO) {
// Browsers supporting crypto.getRandomValues.
if (crypto.getRandomValues) {
a = crypto.getRandomValues(new Uint32Array(k *= 2));
for (; i < k;) {
// 53 bits:
// ((Math.pow(2, 32) - 1) * Math.pow(2, 21)).toString(2)
// 11111 11111111 11111111 11111111 11100000 00000000 00000000
// ((Math.pow(2, 32) - 1) >>> 11).toString(2)
// 11111 11111111 11111111
// 0x20000 is 2^21.
v = a[i] * 0x20000 + (a[i + 1] >>> 11);
// Rejection sampling:
// 0 <= v < 9007199254740992
// Probability that v >= 9e15, is
// 7199254740992 / 9007199254740992 ~= 0.0008, i.e. 1 in 1251
if (v >= 9e15) {
b = crypto.getRandomValues(new Uint32Array(2));
a[i] = b[0];
a[i + 1] = b[1];
} else {
// 0 <= v <= 8999999999999999
// 0 <= (v % 1e14) <= 99999999999999
c.push(v % 1e14);
i += 2;
}
}
i = k / 2;
// Node.js supporting crypto.randomBytes.
} else if (crypto.randomBytes) {
// buffer
a = crypto.randomBytes(k *= 7);
for (; i < k;) {
// 0x1000000000000 is 2^48, 0x10000000000 is 2^40
// 0x100000000 is 2^32, 0x1000000 is 2^24
// 11111 11111111 11111111 11111111 11111111 11111111 11111111
// 0 <= v < 9007199254740992
v = ((a[i] & 31) * 0x1000000000000) + (a[i + 1] * 0x10000000000) +
(a[i + 2] * 0x100000000) + (a[i + 3] * 0x1000000) +
(a[i + 4] << 16) + (a[i + 5] << 8) + a[i + 6];
if (v >= 9e15) {
crypto.randomBytes(7).copy(a, i);
} else {
// 0 <= (v % 1e14) <= 99999999999999
c.push(v % 1e14);
i += 7;
}
}
i = k / 7;
} else {
CRYPTO = false;
if (ERRORS) raise(14, 'crypto unavailable', crypto);
}
}
// Use Math.random.
if (!CRYPTO) {
for (; i < k;) {
v = random53bitInt();
if (v < 9e15) c[i++] = v % 1e14;
}
}
k = c[--i];
dp %= LOG_BASE;
// Convert trailing digits to zeros according to dp.
if (k && dp) {
v = POWS_TEN[LOG_BASE - dp];
c[i] = mathfloor(k / v) * v;
}
// Remove trailing elements which are zero.
for (; c[i] === 0; c.pop(), i--);
// Zero?
if (i < 0) {
c = [e = 0];
} else {
// Remove leading elements which are zero and adjust exponent accordingly.
for (e = -1; c[0] === 0; c.splice(0, 1), e -= LOG_BASE);
// Count the digits of the first element of c to determine leading zeros, and...
for (i = 1, v = c[0]; v >= 10; v /= 10, i++);
// adjust the exponent accordingly.
if (i < LOG_BASE) e -= LOG_BASE - i;
}
rand.e = e;
rand.c = c;
return rand;
};
})();
// PRIVATE FUNCTIONS
// Convert a numeric string of baseIn to a numeric string of baseOut.
function convertBase(str, baseOut, baseIn, sign) {
var d, e, k, r, x, xc, y,
i = str.indexOf('.'),
dp = DECIMAL_PLACES,
rm = ROUNDING_MODE;
if (baseIn < 37) str = str.toLowerCase();
// Non-integer.
if (i >= 0) {
k = POW_PRECISION;
// Unlimited precision.
POW_PRECISION = 0;
str = str.replace('.', '');
y = new BigNumber(baseIn);
x = y.pow(str.length - i);
POW_PRECISION = k;
// Convert str as if an integer, then restore the fraction part by dividing the
// result by its base raised to a power.
y.c = toBaseOut(toFixedPoint(coeffToString(x.c), x.e), 10, baseOut);
y.e = y.c.length;
}
// Convert the number as integer.
xc = toBaseOut(str, baseIn, baseOut);
e = k = xc.length;
// Remove trailing zeros.
for (; xc[--k] == 0; xc.pop());
if (!xc[0]) return '0';
if (i < 0) {
--e;
} else {
x.c = xc;
x.e = e;
// sign is needed for correct rounding.
x.s = sign;
x = div(x, y, dp, rm, baseOut);
xc = x.c;
r = x.r;
e = x.e;
}
d = e + dp + 1;
// The rounding digit, i.e. the digit to the right of the digit that may be rounded up.
i = xc[d];
k = baseOut / 2;
r = r || d < 0 || xc[d + 1] != null;
r = rm < 4 ? (i != null || r) && (rm == 0 || rm == (x.s < 0 ? 3 : 2)) :
i > k || i == k && (rm == 4 || r || rm == 6 && xc[d - 1] & 1 ||
rm == (x.s < 0 ? 8 : 7));
if (d < 1 || !xc[0]) {
// 1^-dp or 0.
str = r ? toFixedPoint('1', -dp) : '0';
} else {
xc.length = d;
if (r) {
// Rounding up may mean the previous digit has to be rounded up and so on.
for (--baseOut; ++xc[--d] > baseOut;) {
xc[d] = 0;
if (!d) {
++e;
xc = [1].concat(xc);
}
}
}
// Determine trailing zeros.
for (k = xc.length; !xc[--k];);
// E.g. [4, 11, 15] becomes 4bf.
for (i = 0, str = ''; i <= k; str += ALPHABET.charAt(xc[i++]));
str = toFixedPoint(str, e);
}
// The caller will add the sign.
return str;
}
// Perform division in the specified base. Called by div and convertBase.
div = (function () {
// Assume non-zero x and k.
function multiply(x, k, base) {
var m, temp, xlo, xhi,
carry = 0,
i = x.length,
klo = k % SQRT_BASE,
khi = k / SQRT_BASE | 0;
for (x = x.slice(); i--;) {
xlo = x[i] % SQRT_BASE;
xhi = x[i] / SQRT_BASE | 0;
m = khi * xlo + xhi * klo;
temp = klo * xlo + ((m % SQRT_BASE) * SQRT_BASE) + carry;
carry = (temp / base | 0) + (m / SQRT_BASE | 0) + khi * xhi;
x[i] = temp % base;
}
if (carry) x = [carry].concat(x);
return x;
}
function compare(a, b, aL, bL) {
var i, cmp;
if (aL != bL) {
cmp = aL > bL ? 1 : -1;
} else {
for (i = cmp = 0; i < aL; i++) {
if (a[i] != b[i]) {
cmp = a[i] > b[i] ? 1 : -1;
break;
}
}
}
return cmp;
}
function subtract(a, b, aL, base) {
var i = 0;
// Subtract b from a.
for (; aL--;) {
a[aL] -= i;
i = a[aL] < b[aL] ? 1 : 0;
a[aL] = i * base + a[aL] - b[aL];
}
// Remove leading zeros.
for (; !a[0] && a.length > 1; a.splice(0, 1));
}
// x: dividend, y: divisor.
return function (x, y, dp, rm, base) {
var cmp, e, i, more, n, prod, prodL, q, qc, rem, remL, rem0, xi, xL, yc0,
yL, yz,
s = x.s == y.s ? 1 : -1,
xc = x.c,
yc = y.c;
// Either NaN, Infinity or 0?
if (!xc || !xc[0] || !yc || !yc[0]) {
return new BigNumber(
// Return NaN if either NaN, or both Infinity or 0.
!x.s || !y.s || (xc ? yc && xc[0] == yc[0] : !yc) ? NaN :
// Return ±0 if x is ±0 or y is ±Infinity, or return ±Infinity as y is ±0.
xc && xc[0] == 0 || !yc ? s * 0 : s / 0
);
}
q = new BigNumber(s);
qc = q.c = [];
e = x.e - y.e;
s = dp + e + 1;
if (!base) {
base = BASE;
e = bitFloor(x.e / LOG_BASE) - bitFloor(y.e / LOG_BASE);
s = s / LOG_BASE | 0;
}
// Result exponent may be one less then the current value of e.
// The coefficients of the BigNumbers from convertBase may have trailing zeros.
for (i = 0; yc[i] == (xc[i] || 0); i++);
if (yc[i] > (xc[i] || 0)) e--;
if (s < 0) {
qc.push(1);
more = true;
} else {
xL = xc.length;
yL = yc.length;
i = 0;
s += 2;
// Normalise xc and yc so highest order digit of yc is >= base / 2.
n = mathfloor(base / (yc[0] + 1));
// Not necessary, but to handle odd bases where yc[0] == ( base / 2 ) - 1.
// if ( n > 1 || n++ == 1 && yc[0] < base / 2 ) {
if (n > 1) {
yc = multiply(yc, n, base);
xc = multiply(xc, n, base);
yL = yc.length;
xL = xc.length;
}
xi = yL;
rem = xc.slice(0, yL);
remL = rem.length;
// Add zeros to make remainder as long as divisor.
for (; remL < yL; rem[remL++] = 0);
yz = yc.slice();
yz = [0].concat(yz);
yc0 = yc[0];
if (yc[1] >= base / 2) yc0++;
// Not necessary, but to prevent trial digit n > base, when using base 3.
// else if ( base == 3 && yc0 == 1 ) yc0 = 1 + 1e-15;
do {
n = 0;
// Compare divisor and remainder.
cmp = compare(yc, rem, yL, remL);
// If divisor < remainder.
if (cmp < 0) {
// Calculate trial digit, n.
rem0 = rem[0];
if (yL != remL) rem0 = rem0 * base + (rem[1] || 0);
// n is how many times the divisor goes into the current remainder.
n = mathfloor(rem0 / yc0);
// Algorithm:
// 1. product = divisor * trial digit (n)
// 2. if product > remainder: product -= divisor, n--
// 3. remainder -= product
// 4. if product was < remainder at 2:
// 5. compare new remainder and divisor
// 6. If remainder > divisor: remainder -= divisor, n++
if (n > 1) {
// n may be > base only when base is 3.
if (n >= base) n = base - 1;
// product = divisor * trial digit.
prod = multiply(yc, n, base);
prodL = prod.length;
remL = rem.length;
// Compare product and remainder.
// If product > remainder.
// Trial digit n too high.
// n is 1 too high about 5% of the time, and is not known to have
// ever been more than 1 too high.
while (compare(prod, rem, prodL, remL) == 1) {
n--;
// Subtract divisor from product.
subtract(prod, yL < prodL ? yz : yc, prodL, base);
prodL = prod.length;
cmp = 1;
}
} else {
// n is 0 or 1, cmp is -1.
// If n is 0, there is no need to compare yc and rem again below,
// so change cmp to 1 to avoid it.
// If n is 1, leave cmp as -1, so yc and rem are compared again.
if (n == 0) {
// divisor < remainder, so n must be at least 1.
cmp = n = 1;
}
// product = divisor
prod = yc.slice();
prodL = prod.length;
}
if (prodL < remL) prod = [0].concat(prod);
// Subtract product from remainder.
subtract(rem, prod, remL, base);
remL = rem.length;
// If product was < remainder.
if (cmp == -1) {
// Compare divisor and new remainder.
// If divisor < new remainder, subtract divisor from remainder.
// Trial digit n too low.
// n is 1 too low about 5% of the time, and very rarely 2 too low.
while (compare(yc, rem, yL, remL) < 1) {
n++;
// Subtract divisor from remainder.
subtract(rem, yL < remL ? yz : yc, remL, base);
remL = rem.length;
}
}
} else if (cmp === 0) {
n++;
rem = [0];
} // else cmp === 1 and n will be 0
// Add the next digit, n, to the result array.
qc[i++] = n;
// Update the remainder.
if (rem[0]) {
rem[remL++] = xc[xi] || 0;
} else {
rem = [xc[xi]];
remL = 1;
}
} while ((xi++ < xL || rem[0] != null) && s--);
more = rem[0] != null;
// Leading zero?
if (!qc[0]) qc.splice(0, 1);
}
if (base == BASE) {
// To calculate q.e, first get the number of digits of qc[0].
for (i = 1, s = qc[0]; s >= 10; s /= 10, i++);
round(q, dp + (q.e = i + e * LOG_BASE - 1) + 1, rm, more);
// Caller is convertBase.
} else {
q.e = e;
q.r = +more;
}
return q;
};
})();
/*
* Return a string representing the value of BigNumber n in fixed-point or exponential
* notation rounded to the specified decimal places or significant digits.
*
* n is a BigNumber.
* i is the index of the last digit required (i.e. the digit that may be rounded up).
* rm is the rounding mode.
* caller is caller id: toExponential 19, toFixed 20, toFormat 21, toPrecision 24.
*/
function format(n, i, rm, caller) {
var c0, e, ne, len, str;
rm = rm != null && isValidInt(rm, 0, 8, caller, roundingMode) ?
rm | 0 : ROUNDING_MODE;
if (!n.c) return n.toString();
c0 = n.c[0];
ne = n.e;
if (i == null) {
str = coeffToString(n.c);
str = caller == 19 || caller == 24 && ne <= TO_EXP_NEG ?
toExponential(str, ne) :
toFixedPoint(str, ne);
} else {
n = round(new BigNumber(n), i, rm);
// n.e may have changed if the value was rounded up.
e = n.e;
str = coeffToString(n.c);
len = str.length;
// toPrecision returns exponential notation if the number of significant digits
// specified is less than the number of digits necessary to represent the integer
// part of the value in fixed-point notation.
// Exponential notation.
if (caller == 19 || caller == 24 && (i <= e || e <= TO_EXP_NEG)) {
// Append zeros?
for (; len < i; str += '0', len++);
str = toExponential(str, e);
// Fixed-point notation.
} else {
i -= ne;
str = toFixedPoint(str, e);
// Append zeros?
if (e + 1 > len) {
if (--i > 0)
for (str += '.'; i--; str += '0');
} else {
i += e - len;
if (i > 0) {
if (e + 1 == len) str += '.';
for (; i--; str += '0');
}
}
}
}
return n.s < 0 && c0 ? '-' + str : str;
}
// Handle BigNumber.max and BigNumber.min.
function maxOrMin(args, method) {
var m, n,
i = 0;
if (isArray(args[0])) args = args[0];
m = new BigNumber(args[0]);
for (; ++i < args.length;) {
n = new BigNumber(args[i]);
// If any number is NaN, return NaN.
if (!n.s) {
m = n;
break;
} else if (method.call(m, n)) {
m = n;
}
}
return m;
}
/*
* Return true if n is an integer in range, otherwise throw.
* Use for argument validation when ERRORS is true.
*/
function intValidatorWithErrors(n, min, max, caller, name) {
if (n < min || n > max || n != truncate(n)) {
raise(caller, (name || 'decimal places') +
(n < min || n > max ? ' out of range' : ' not an integer'), n);
}
return true;
}
/*
* Strip trailing zeros, calculate base 10 exponent and check against MIN_EXP and MAX_EXP.
* Called by minus, plus and times.
*/
function normalise(n, c, e) {
var i = 1,
j = c.length;
// Remove trailing zeros.
for (; !c[--j]; c.pop());
// Calculate the base 10 exponent. First get the number of digits of c[0].
for (j = c[0]; j >= 10; j /= 10, i++);
// Overflow?
if ((e = i + e * LOG_BASE - 1) > MAX_EXP) {
// Infinity.
n.c = n.e = null;
// Underflow?
} else if (e < MIN_EXP) {
// Zero.
n.c = [n.e = 0];
} else {
n.e = e;
n.c = c;
}
return n;
}
// Handle values that fail the validity test in BigNumber.
parseNumeric = (function () {
var basePrefix = /^(-?)0([xbo])(?=\w[\w.]*$)/i,
dotAfter = /^([^.]+)\.$/,
dotBefore = /^\.([^.]+)$/,
isInfinityOrNaN = /^-?(Infinity|NaN)$/,
whitespaceOrPlus = /^\s*\+(?=[\w.])|^\s+|\s+$/g;
return function (x, str, num, b) {
var base,
s = num ? str : str.replace(whitespaceOrPlus, '');
// No exception on ±Infinity or NaN.
if (isInfinityOrNaN.test(s)) {
x.s = isNaN(s) ? null : s < 0 ? -1 : 1;
} else {
if (!num) {
// basePrefix = /^(-?)0([xbo])(?=\w[\w.]*$)/i
s = s.replace(basePrefix, function (m, p1, p2) {
base = (p2 = p2.toLowerCase()) == 'x' ? 16 : p2 == 'b' ? 2 : 8;
return !b || b == base ? p1 : m;
});
if (b) {
base = b;
// E.g. '1.' to '1', '.1' to '0.1'
s = s.replace(dotAfter, '$1').replace(dotBefore, '0.$1');
}
if (str != s) return new BigNumber(s, base);
}
// 'new BigNumber() not a number: {n}'
// 'new BigNumber() not a base {b} number: {n}'
if (ERRORS) raise(id, 'not a' + (b ? ' base ' + b : '') + ' number', str);
x.s = null;
}
x.c = x.e = null;
id = 0;
}
})();
// Throw a BigNumber Error.
function raise(caller, msg, val) {
var error = new Error([
'new BigNumber', // 0
'cmp', // 1
'config', // 2
'div', // 3
'divToInt', // 4
'eq', // 5
'gt', // 6
'gte', // 7
'lt', // 8
'lte', // 9
'minus', // 10
'mod', // 11
'plus', // 12
'precision', // 13
'random', // 14
'round', // 15
'shift', // 16
'times', // 17
'toDigits', // 18
'toExponential', // 19
'toFixed', // 20
'toFormat', // 21
'toFraction', // 22
'pow', // 23
'toPrecision', // 24
'toString', // 25
'BigNumber' // 26
][caller] + '() ' + msg + ': ' + val);
error.name = 'BigNumber Error';
id = 0;
throw error;
}
/*
* Round x to sd significant digits using rounding mode rm. Check for over/under-flow.
* If r is truthy, it is known that there are more digits after the rounding digit.
*/
function round(x, sd, rm, r) {
var d, i, j, k, n, ni, rd,
xc = x.c,
pows10 = POWS_TEN;
// if x is not Infinity or NaN...
if (xc) {
// rd is the rounding digit, i.e. the digit after the digit that may be rounded up.
// n is a base 1e14 number, the value of the element of array x.c containing rd.
// ni is the index of n within x.c.
// d is the number of digits of n.
// i is the index of rd within n including leading zeros.
// j is the actual index of rd within n (if < 0, rd is a leading zero).
out: {
// Get the number of digits of the first element of xc.
for (d = 1, k = xc[0]; k >= 10; k /= 10, d++);
i = sd - d;
// If the rounding digit is in the first element of xc...
if (i < 0) {
i += LOG_BASE;
j = sd;
n = xc[ni = 0];
// Get the rounding digit at index j of n.
rd = n / pows10[d - j - 1] % 10 | 0;
} else {
ni = mathceil((i + 1) / LOG_BASE);
if (ni >= xc.length) {
if (r) {
// Needed by sqrt.
for (; xc.length <= ni; xc.push(0));
n = rd = 0;
d = 1;
i %= LOG_BASE;
j = i - LOG_BASE + 1;
} else {
break out;
}
} else {
n = k = xc[ni];
// Get the number of digits of n.
for (d = 1; k >= 10; k /= 10, d++);
// Get the index of rd within n.
i %= LOG_BASE;
// Get the index of rd within n, adjusted for leading zeros.
// The number of leading zeros of n is given by LOG_BASE - d.
j = i - LOG_BASE + d;
// Get the rounding digit at index j of n.
rd = j < 0 ? 0 : n / pows10[d - j - 1] % 10 | 0;
}
}
r = r || sd < 0 ||
// Are there any non-zero digits after the rounding digit?
// The expression n % pows10[ d - j - 1 ] returns all digits of n to the right
// of the digit at j, e.g. if n is 908714 and j is 2, the expression gives 714.
xc[ni + 1] != null || (j < 0 ? n : n % pows10[d - j - 1]);
r = rm < 4 ?
(rd || r) && (rm == 0 || rm == (x.s < 0 ? 3 : 2)) : rd > 5 || rd == 5 && (rm == 4 || r || rm == 6 &&
// Check whether the digit to the left of the rounding digit is odd.
((i > 0 ? j > 0 ? n / pows10[d - j] : 0 : xc[ni - 1]) % 10) & 1 ||
rm == (x.s < 0 ? 8 : 7));
if (sd < 1 || !xc[0]) {
xc.length = 0;
if (r) {
// Convert sd to decimal places.
sd -= x.e + 1;
// 1, 0.1, 0.01, 0.001, 0.0001 etc.
xc[0] = pows10[(LOG_BASE - sd % LOG_BASE) % LOG_BASE];
x.e = -sd || 0;
} else {
// Zero.
xc[0] = x.e = 0;
}
return x;
}
// Remove excess digits.
if (i == 0) {
xc.length = ni;
k = 1;
ni--;
} else {
xc.length = ni + 1;
k = pows10[LOG_BASE - i];
// E.g. 56700 becomes 56000 if 7 is the rounding digit.
// j > 0 means i > number of leading zeros of n.
xc[ni] = j > 0 ? mathfloor(n / pows10[d - j] % pows10[j]) * k : 0;
}
// Round up?
if (r) {
for (;;) {
// If the digit to be rounded up is in the first element of xc...
if (ni == 0) {
// i will be the length of xc[0] before k is added.
for (i = 1, j = xc[0]; j >= 10; j /= 10, i++);
j = xc[0] += k;
for (k = 1; j >= 10; j /= 10, k++);
// if i != k the length has increased.
if (i != k) {
x.e++;
if (xc[0] == BASE) xc[0] = 1;
}
break;
} else {
xc[ni] += k;
if (xc[ni] != BASE) break;
xc[ni--] = 0;
k = 1;
}
}
}
// Remove trailing zeros.
for (i = xc.length; xc[--i] === 0; xc.pop());
}
// Overflow? Infinity.
if (x.e > MAX_EXP) {
x.c = x.e = null;
// Underflow? Zero.
} else if (x.e < MIN_EXP) {
x.c = [x.e = 0];
}
}
return x;
}
// PROTOTYPE/INSTANCE METHODS
/*
* Return a new BigNumber whose value is the absolute value of this BigNumber.
*/
P.absoluteValue = P.abs = function () {
var x = new BigNumber(this);
if (x.s < 0) x.s = 1;
return x;
};
/*
* Return a new BigNumber whose value is the value of this BigNumber rounded to a whole
* number in the direction of Infinity.
*/
P.ceil = function () {
return round(new BigNumber(this), this.e + 1, 2);
};
/*
* Return
* 1 if the value of this BigNumber is greater than the value of BigNumber(y, b),
* -1 if the value of this BigNumber is less than the value of BigNumber(y, b),
* 0 if they have the same value,
* or null if the value of either is NaN.
*/
P.comparedTo = P.cmp = function (y, b) {
id = 1;
return compare(this, new BigNumber(y, b));
};
/*
* Return the number of decimal places of the value of this BigNumber, or null if the value
* of this BigNumber is ±Infinity or NaN.
*/
P.decimalPlaces = P.dp = function () {
var n, v,
c = this.c;
if (!c) return null;
n = ((v = c.length - 1) - bitFloor(this.e / LOG_BASE)) * LOG_BASE;
// Subtract the number of trailing zeros of the last number.
if (v = c[v])
for (; v % 10 == 0; v /= 10, n--);
if (n < 0) n = 0;
return n;
};
/*
* n / 0 = I
* n / N = N
* n / I = 0
* 0 / n = 0
* 0 / 0 = N
* 0 / N = N
* 0 / I = 0
* N / n = N
* N / 0 = N
* N / N = N
* N / I = N
* I / n = I
* I / 0 = I
* I / N = N
* I / I = N
*
* Return a new BigNumber whose value is the value of this BigNumber divided by the value of
* BigNumber(y, b), rounded according to DECIMAL_PLACES and ROUNDING_MODE.
*/
P.dividedBy = P.div = function (y, b) {
id = 3;
return div(this, new BigNumber(y, b), DECIMAL_PLACES, ROUNDING_MODE);
};
/*
* Return a new BigNumber whose value is the integer part of dividing the value of this
* BigNumber by the value of BigNumber(y, b).
*/
P.dividedToIntegerBy = P.divToInt = function (y, b) {
id = 4;
return div(this, new BigNumber(y, b), 0, 1);
};
/*
* Return true if the value of this BigNumber is equal to the value of BigNumber(y, b),
* otherwise returns false.
*/
P.equals = P.eq = function (y, b) {
id = 5;
return compare(this, new BigNumber(y, b)) === 0;
};
/*
* Return a new BigNumber whose value is the value of this BigNumber rounded to a whole
* number in the direction of -Infinity.
*/
P.floor = function () {
return round(new BigNumber(this), this.e + 1, 3);
};
/*
* Return true if the value of this BigNumber is greater than the value of BigNumber(y, b),
* otherwise returns false.
*/
P.greaterThan = P.gt = function (y, b) {
id = 6;
return compare(this, new BigNumber(y, b)) > 0;
};
/*
* Return true if the value of this BigNumber is greater than or equal to the value of
* BigNumber(y, b), otherwise returns false.
*/
P.greaterThanOrEqualTo = P.gte = function (y, b) {
id = 7;
return (b = compare(this, new BigNumber(y, b))) === 1 || b === 0;
};
/*
* Return true if the value of this BigNumber is a finite number, otherwise returns false.
*/
P.isFinite = function () {
return !!this.c;
};
/*
* Return true if the value of this BigNumber is an integer, otherwise return false.
*/
P.isInteger = P.isInt = function () {
return !!this.c && bitFloor(this.e / LOG_BASE) > this.c.length - 2;
};
/*
* Return true if the value of this BigNumber is NaN, otherwise returns false.
*/
P.isNaN = function () {
return !this.s;
};
/*
* Return true if the value of this BigNumber is negative, otherwise returns false.
*/
P.isNegative = P.isNeg = function () {
return this.s < 0;
};
/*
* Return true if the value of this BigNumber is 0 or -0, otherwise returns false.
*/
P.isZero = function () {
return !!this.c && this.c[0] == 0;
};
/*
* Return true if the value of this BigNumber is less than the value of BigNumber(y, b),
* otherwise returns false.
*/
P.lessThan = P.lt = function (y, b) {
id = 8;
return compare(this, new BigNumber(y, b)) < 0;
};
/*
* Return true if the value of this BigNumber is less than or equal to the value of
* BigNumber(y, b), otherwise returns false.
*/
P.lessThanOrEqualTo = P.lte = function (y, b) {
id = 9;
return (b = compare(this, new BigNumber(y, b))) === -1 || b === 0;
};
/*
* n - 0 = n
* n - N = N
* n - I = -I
* 0 - n = -n
* 0 - 0 = 0
* 0 - N = N
* 0 - I = -I
* N - n = N
* N - 0 = N
* N - N = N
* N - I = N
* I - n = I
* I - 0 = I
* I - N = N
* I - I = N
*
* Return a new BigNumber whose value is the value of this BigNumber minus the value of
* BigNumber(y, b).
*/
P.minus = P.sub = function (y, b) {
var i, j, t, xLTy,
x = this,
a = x.s;
id = 10;
y = new BigNumber(y, b);
b = y.s;
// Either NaN?
if (!a || !b) return new BigNumber(NaN);
// Signs differ?
if (a != b) {
y.s = -b;
return x.plus(y);
}
var xe = x.e / LOG_BASE,
ye = y.e / LOG_BASE,
xc = x.c,
yc = y.c;
if (!xe || !ye) {
// Either Infinity?
if (!xc || !yc) return xc ? (y.s = -b, y) : new BigNumber(yc ? x : NaN);
// Either zero?
if (!xc[0] || !yc[0]) {
// Return y if y is non-zero, x if x is non-zero, or zero if both are zero.
return yc[0] ? (y.s = -b, y) : new BigNumber(xc[0] ? x :
// IEEE 754 (2008) 6.3: n - n = -0 when rounding to -Infinity
ROUNDING_MODE == 3 ? -0 : 0);
}
}
xe = bitFloor(xe);
ye = bitFloor(ye);
xc = xc.slice();
// Determine which is the bigger number.
if (a = xe - ye) {
if (xLTy = a < 0) {
a = -a;
t = xc;
} else {
ye = xe;
t = yc;
}
t.reverse();
// Prepend zeros to equalise exponents.
for (b = a; b--; t.push(0));
t.reverse();
} else {
// Exponents equal. Check digit by digit.
j = (xLTy = (a = xc.length) < (b = yc.length)) ? a : b;
for (a = b = 0; b < j; b++) {
if (xc[b] != yc[b]) {
xLTy = xc[b] < yc[b];
break;
}
}
}
// x < y? Point xc to the array of the bigger number.
if (xLTy) t = xc, xc = yc, yc = t, y.s = -y.s;
b = (j = yc.length) - (i = xc.length);
// Append zeros to xc if shorter.
// No need to add zeros to yc if shorter as subtract only needs to start at yc.length.
if (b > 0)
for (; b--; xc[i++] = 0);
b = BASE - 1;
// Subtract yc from xc.
for (; j > a;) {
if (xc[--j] < yc[j]) {
for (i = j; i && !xc[--i]; xc[i] = b);
--xc[i];
xc[j] += BASE;
}
xc[j] -= yc[j];
}
// Remove leading zeros and adjust exponent accordingly.
for (; xc[0] == 0; xc.splice(0, 1), --ye);
// Zero?
if (!xc[0]) {
// Following IEEE 754 (2008) 6.3,
// n - n = +0 but n - n = -0 when rounding towards -Infinity.
y.s = ROUNDING_MODE == 3 ? -1 : 1;
y.c = [y.e = 0];
return y;
}
// No need to check for Infinity as +x - +y != Infinity && -x - -y != Infinity
// for finite x and y.
return normalise(y, xc, ye);
};
/*
* n % 0 = N
* n % N = N
* n % I = n
* 0 % n = 0
* -0 % n = -0
* 0 % 0 = N
* 0 % N = N
* 0 % I = 0
* N % n = N
* N % 0 = N
* N % N = N
* N % I = N
* I % n = N
* I % 0 = N
* I % N = N
* I % I = N
*
* Return a new BigNumber whose value is the value of this BigNumber modulo the value of
* BigNumber(y, b). The result depends on the value of MODULO_MODE.
*/
P.modulo = P.mod = function (y, b) {
var q, s,
x = this;
id = 11;
y = new BigNumber(y, b);
// Return NaN if x is Infinity or NaN, or y is NaN or zero.
if (!x.c || !y.s || y.c && !y.c[0]) {
return new BigNumber(NaN);
// Return x if y is Infinity or x is zero.
} else if (!y.c || x.c && !x.c[0]) {
return new BigNumber(x);
}
if (MODULO_MODE == 9) {
// Euclidian division: q = sign(y) * floor(x / abs(y))
// r = x - qy where 0 <= r < abs(y)
s = y.s;
y.s = 1;
q = div(x, y, 0, 3);
y.s = s;
q.s *= s;
} else {
q = div(x, y, 0, MODULO_MODE);
}
return x.minus(q.times(y));
};
/*
* Return a new BigNumber whose value is the value of this BigNumber negated,
* i.e. multiplied by -1.
*/
P.negated = P.neg = function () {
var x = new BigNumber(this);
x.s = -x.s || null;
return x;
};
/*
* n + 0 = n
* n + N = N
* n + I = I
* 0 + n = n
* 0 + 0 = 0
* 0 + N = N
* 0 + I = I
* N + n = N
* N + 0 = N
* N + N = N
* N + I = N
* I + n = I
* I + 0 = I
* I + N = N
* I + I = I
*
* Return a new BigNumber whose value is the value of this BigNumber plus the value of
* BigNumber(y, b).
*/
P.plus = P.add = function (y, b) {
var t,
x = this,
a = x.s;
id = 12;
y = new BigNumber(y, b);
b = y.s;
// Either NaN?
if (!a || !b) return new BigNumber(NaN);
// Signs differ?
if (a != b) {
y.s = -b;
return x.minus(y);
}
var xe = x.e / LOG_BASE,
ye = y.e / LOG_BASE,
xc = x.c,
yc = y.c;
if (!xe || !ye) {
// Return ±Infinity if either ±Infinity.
if (!xc || !yc) return new BigNumber(a / 0);
// Either zero?
// Return y if y is non-zero, x if x is non-zero, or zero if both are zero.
if (!xc[0] || !yc[0]) return yc[0] ? y : new BigNumber(xc[0] ? x : a * 0);
}
xe = bitFloor(xe);
ye = bitFloor(ye);
xc = xc.slice();
// Prepend zeros to equalise exponents. Faster to use reverse then do unshifts.
if (a = xe - ye) {
if (a > 0) {
ye = xe;
t = yc;
} else {
a = -a;
t = xc;
}
t.reverse();
for (; a--; t.push(0));
t.reverse();
}
a = xc.length;
b = yc.length;
// Point xc to the longer array, and b to the shorter length.
if (a - b < 0) t = yc, yc = xc, xc = t, b = a;
// Only start adding at yc.length - 1 as the further digits of xc can be ignored.
for (a = 0; b;) {
a = (xc[--b] = xc[b] + yc[b] + a) / BASE | 0;
xc[b] = BASE === xc[b] ? 0 : xc[b] % BASE;
}
if (a) {
xc = [a].concat(xc);
++ye;
}
// No need to check for zero, as +x + +y != 0 && -x + -y != 0
// ye = MAX_EXP + 1 possible
return normalise(y, xc, ye);
};
/*
* Return the number of significant digits of the value of this BigNumber.
*
* [z] {boolean|number} Whether to count integer-part trailing zeros: true, false, 1 or 0.
*/
P.precision = P.sd = function (z) {
var n, v,
x = this,
c = x.c;
// 'precision() argument not a boolean or binary digit: {z}'
if (z != null && z !== !!z && z !== 1 && z !== 0) {
if (ERRORS) raise(13, 'argument' + notBool, z);
if (z != !!z) z = null;
}
if (!c) return null;
v = c.length - 1;
n = v * LOG_BASE + 1;
if (v = c[v]) {
// Subtract the number of trailing zeros of the last element.
for (; v % 10 == 0; v /= 10, n--);
// Add the number of digits of the first element.
for (v = c[0]; v >= 10; v /= 10, n++);
}
if (z && x.e + 1 > n) n = x.e + 1;
return n;
};
/*
* Return a new BigNumber whose value is the value of this BigNumber rounded to a maximum of
* dp decimal places using rounding mode rm, or to 0 and ROUNDING_MODE respectively if
* omitted.
*
* [dp] {number} Decimal places. Integer, 0 to MAX inclusive.
* [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
*
* 'round() decimal places out of range: {dp}'
* 'round() decimal places not an integer: {dp}'
* 'round() rounding mode not an integer: {rm}'
* 'round() rounding mode out of range: {rm}'
*/
P.round = function (dp, rm) {
var n = new BigNumber(this);
if (dp == null || isValidInt(dp, 0, MAX, 15)) {
round(n, ~~dp + this.e + 1, rm == null ||
!isValidInt(rm, 0, 8, 15, roundingMode) ? ROUNDING_MODE : rm | 0);
}
return n;
};
/*
* Return a new BigNumber whose value is the value of this BigNumber shifted by k places
* (powers of 10). Shift to the right if n > 0, and to the left if n < 0.
*
* k {number} Integer, -MAX_SAFE_INTEGER to MAX_SAFE_INTEGER inclusive.
*
* If k is out of range and ERRORS is false, the result will be ±0 if k < 0, or ±Infinity
* otherwise.
*
* 'shift() argument not an integer: {k}'
* 'shift() argument out of range: {k}'
*/
P.shift = function (k) {
var n = this;
return isValidInt(k, -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER, 16, 'argument')
// k < 1e+21, or truncate(k) will produce exponential notation.
?
n.times('1e' + truncate(k)) :
new BigNumber(n.c && n.c[0] && (k < -MAX_SAFE_INTEGER || k > MAX_SAFE_INTEGER) ?
n.s * (k < 0 ? 0 : 1 / 0) :
n);
};
/*
* sqrt(-n) = N
* sqrt( N) = N
* sqrt(-I) = N
* sqrt( I) = I
* sqrt( 0) = 0
* sqrt(-0) = -0
*
* Return a new BigNumber whose value is the square root of the value of this BigNumber,
* rounded according to DECIMAL_PLACES and ROUNDING_MODE.
*/
P.squareRoot = P.sqrt = function () {
var m, n, r, rep, t,
x = this,
c = x.c,
s = x.s,
e = x.e,
dp = DECIMAL_PLACES + 4,
half = new BigNumber('0.5');
// Negative/NaN/Infinity/zero?
if (s !== 1 || !c || !c[0]) {
return new BigNumber(!s || s < 0 && (!c || c[0]) ? NaN : c ? x : 1 / 0);
}
// Initial estimate.
s = Math.sqrt(+x);
// Math.sqrt underflow/overflow?
// Pass x to Math.sqrt as integer, then adjust the exponent of the result.
if (s == 0 || s == 1 / 0) {
n = coeffToString(c);
if ((n.length + e) % 2 == 0) n += '0';
s = Math.sqrt(n);
e = bitFloor((e + 1) / 2) - (e < 0 || e % 2);
if (s == 1 / 0) {
n = '1e' + e;
} else {
n = s.toExponential();
n = n.slice(0, n.indexOf('e') + 1) + e;
}
r = new BigNumber(n);
} else {
r = new BigNumber(s + '');
}
// Check for zero.
// r could be zero if MIN_EXP is changed after the this value was created.
// This would cause a division by zero (x/t) and hence Infinity below, which would cause
// coeffToString to throw.
if (r.c[0]) {
e = r.e;
s = e + dp;
if (s < 3) s = 0;
// Newton-Raphson iteration.
for (;;) {
t = r;
r = half.times(t.plus(div(x, t, dp, 1)));
if (coeffToString(t.c).slice(0, s) === (n =
coeffToString(r.c)).slice(0, s)) {
// The exponent of r may here be one less than the final result exponent,
// e.g 0.0009999 (e-4) --> 0.001 (e-3), so adjust s so the rounding digits
// are indexed correctly.
if (r.e < e) --s;
n = n.slice(s - 3, s + 1);
// The 4th rounding digit may be in error by -1 so if the 4 rounding digits
// are 9999 or 4999 (i.e. approaching a rounding boundary) continue the
// iteration.
if (n == '9999' || !rep && n == '4999') {
// On the first iteration only, check to see if rounding up gives the
// exact result as the nines may infinitely repeat.
if (!rep) {
round(t, t.e + DECIMAL_PLACES + 2, 0);
if (t.times(t).eq(x)) {
r = t;
break;
}
}
dp += 4;
s += 4;
rep = 1;
} else {
// If rounding digits are null, 0{0,4} or 50{0,3}, check for exact
// result. If not, then there are further digits and m will be truthy.
if (!+n || !+n.slice(1) && n.charAt(0) == '5') {
// Truncate to the first rounding digit.
round(r, r.e + DECIMAL_PLACES + 2, 1);
m = !r.times(r).eq(x);
}
break;
}
}
}
}
return round(r, r.e + DECIMAL_PLACES + 1, ROUNDING_MODE, m);
};
/*
* n * 0 = 0
* n * N = N
* n * I = I
* 0 * n = 0
* 0 * 0 = 0
* 0 * N = N
* 0 * I = N
* N * n = N
* N * 0 = N
* N * N = N
* N * I = N
* I * n = I
* I * 0 = N
* I * N = N
* I * I = I
*
* Return a new BigNumber whose value is the value of this BigNumber times the value of
* BigNumber(y, b).
*/
P.times = P.mul = function (y, b) {
var c, e, i, j, k, m, xcL, xlo, xhi, ycL, ylo, yhi, zc,
base, sqrtBase,
x = this,
xc = x.c,
yc = (id = 17, y = new BigNumber(y, b)).c;
// Either NaN, ±Infinity or ±0?
if (!xc || !yc || !xc[0] || !yc[0]) {
// Return NaN if either is NaN, or one is 0 and the other is Infinity.
if (!x.s || !y.s || xc && !xc[0] && !yc || yc && !yc[0] && !xc) {
y.c = y.e = y.s = null;
} else {
y.s *= x.s;
// Return ±Infinity if either is ±Infinity.
if (!xc || !yc) {
y.c = y.e = null;
// Return ±0 if either is ±0.
} else {
y.c = [0];
y.e = 0;
}
}
return y;
}
e = bitFloor(x.e / LOG_BASE) + bitFloor(y.e / LOG_BASE);
y.s *= x.s;
xcL = xc.length;
ycL = yc.length;
// Ensure xc points to longer array and xcL to its length.
if (xcL < ycL) zc = xc, xc = yc, yc = zc, i = xcL, xcL = ycL, ycL = i;
// Initialise the result array with zeros.
for (i = xcL + ycL, zc = []; i--; zc.push(0));
base = BASE;
sqrtBase = SQRT_BASE;
for (i = ycL; --i >= 0;) {
c = 0;
ylo = yc[i] % sqrtBase;
yhi = yc[i] / sqrtBase | 0;
for (k = xcL, j = i + k; j > i;) {
xlo = xc[--k] % sqrtBase;
xhi = xc[k] / sqrtBase | 0;
m = yhi * xlo + xhi * ylo;
xlo = ylo * xlo + ((m % sqrtBase) * sqrtBase) + zc[j] + c;
c = (xlo / base | 0) + (m / sqrtBase | 0) + yhi * xhi;
zc[j--] = xlo % base;
}
zc[j] = c;
}
if (c) {
++e;
} else {
zc.splice(0, 1);
}
return normalise(y, zc, e);
};
/*
* Return a new BigNumber whose value is the value of this BigNumber rounded to a maximum of
* sd significant digits using rounding mode rm, or ROUNDING_MODE if rm is omitted.
*
* [sd] {number} Significant digits. Integer, 1 to MAX inclusive.
* [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
*
* 'toDigits() precision out of range: {sd}'
* 'toDigits() precision not an integer: {sd}'
* 'toDigits() rounding mode not an integer: {rm}'
* 'toDigits() rounding mode out of range: {rm}'
*/
P.toDigits = function (sd, rm) {
var n = new BigNumber(this);
sd = sd == null || !isValidInt(sd, 1, MAX, 18, 'precision') ? null : sd | 0;
rm = rm == null || !isValidInt(rm, 0, 8, 18, roundingMode) ? ROUNDING_MODE : rm | 0;
return sd ? round(n, sd, rm) : n;
};
/*
* Return a string representing the value of this BigNumber in exponential notation and
* rounded using ROUNDING_MODE to dp fixed decimal places.
*
* [dp] {number} Decimal places. Integer, 0 to MAX inclusive.
* [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
*
* 'toExponential() decimal places not an integer: {dp}'
* 'toExponential() decimal places out of range: {dp}'
* 'toExponential() rounding mode not an integer: {rm}'
* 'toExponential() rounding mode out of range: {rm}'
*/
P.toExponential = function (dp, rm) {
return format(this,
dp != null && isValidInt(dp, 0, MAX, 19) ? ~~dp + 1 : null, rm, 19);
};
/*
* Return a string representing the value of this BigNumber in fixed-point notation rounding
* to dp fixed decimal places using rounding mode rm, or ROUNDING_MODE if rm is omitted.
*
* Note: as with JavaScript's number type, (-0).toFixed(0) is '0',
* but e.g. (-0.00001).toFixed(0) is '-0'.
*
* [dp] {number} Decimal places. Integer, 0 to MAX inclusive.
* [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
*
* 'toFixed() decimal places not an integer: {dp}'
* 'toFixed() decimal places out of range: {dp}'
* 'toFixed() rounding mode not an integer: {rm}'
* 'toFixed() rounding mode out of range: {rm}'
*/
P.toFixed = function (dp, rm) {
return format(this, dp != null && isValidInt(dp, 0, MAX, 20) ?
~~dp + this.e + 1 : null, rm, 20);
};
/*
* Return a string representing the value of this BigNumber in fixed-point notation rounded
* using rm or ROUNDING_MODE to dp decimal places, and formatted according to the properties
* of the FORMAT object (see BigNumber.config).
*
* FORMAT = {
* decimalSeparator : '.',
* groupSeparator : ',',
* groupSize : 3,
* secondaryGroupSize : 0,
* fractionGroupSeparator : '\xA0', // non-breaking space
* fractionGroupSize : 0
* };
*
* [dp] {number} Decimal places. Integer, 0 to MAX inclusive.
* [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
*
* 'toFormat() decimal places not an integer: {dp}'
* 'toFormat() decimal places out of range: {dp}'
* 'toFormat() rounding mode not an integer: {rm}'
* 'toFormat() rounding mode out of range: {rm}'
*/
P.toFormat = function (dp, rm) {
var str = format(this, dp != null && isValidInt(dp, 0, MAX, 21) ?
~~dp + this.e + 1 : null, rm, 21);
if (this.c) {
var i,
arr = str.split('.'),
g1 = +FORMAT.groupSize,
g2 = +FORMAT.secondaryGroupSize,
groupSeparator = FORMAT.groupSeparator,
intPart = arr[0],
fractionPart = arr[1],
isNeg = this.s < 0,
intDigits = isNeg ? intPart.slice(1) : intPart,
len = intDigits.length;
if (g2) i = g1, g1 = g2, g2 = i, len -= i;
if (g1 > 0 && len > 0) {
i = len % g1 || g1;
intPart = intDigits.substr(0, i);
for (; i < len; i += g1) {
intPart += groupSeparator + intDigits.substr(i, g1);
}
if (g2 > 0) intPart += groupSeparator + intDigits.slice(i);
if (isNeg) intPart = '-' + intPart;
}
str = fractionPart ?
intPart + FORMAT.decimalSeparator + ((g2 = +FORMAT.fractionGroupSize) ?
fractionPart.replace(new RegExp('\\d{' + g2 + '}\\B', 'g'),
'$&' + FORMAT.fractionGroupSeparator) :
fractionPart) :
intPart;
}
return str;
};
/*
* Return a string array representing the value of this BigNumber as a simple fraction with
* an integer numerator and an integer denominator. The denominator will be a positive
* non-zero value less than or equal to the specified maximum denominator. If a maximum
* denominator is not specified, the denominator will be the lowest value necessary to
* represent the number exactly.
*
* [md] {number|string|BigNumber} Integer >= 1 and < Infinity. The maximum denominator.
*
* 'toFraction() max denominator not an integer: {md}'
* 'toFraction() max denominator out of range: {md}'
*/
P.toFraction = function (md) {
var arr, d0, d2, e, exp, n, n0, q, s,
k = ERRORS,
x = this,
xc = x.c,
d = new BigNumber(ONE),
n1 = d0 = new BigNumber(ONE),
d1 = n0 = new BigNumber(ONE);
if (md != null) {
ERRORS = false;
n = new BigNumber(md);
ERRORS = k;
if (!(k = n.isInt()) || n.lt(ONE)) {
if (ERRORS) {
raise(22,
'max denominator ' + (k ? 'out of range' : 'not an integer'), md);
}
// ERRORS is false:
// If md is a finite non-integer >= 1, round it to an integer and use it.
md = !k && n.c && round(n, n.e + 1, 1).gte(ONE) ? n : null;
}
}
if (!xc) return x.toString();
s = coeffToString(xc);
// Determine initial denominator.
// d is a power of 10 and the minimum max denominator that specifies the value exactly.
e = d.e = s.length - x.e - 1;
d.c[0] = POWS_TEN[(exp = e % LOG_BASE) < 0 ? LOG_BASE + exp : exp];
md = !md || n.cmp(d) > 0 ? (e > 0 ? d : n1) : n;
exp = MAX_EXP;
MAX_EXP = 1 / 0;
n = new BigNumber(s);
// n0 = d1 = 0
n0.c[0] = 0;
for (;;) {
q = div(n, d, 0, 1);
d2 = d0.plus(q.times(d1));
if (d2.cmp(md) == 1) break;
d0 = d1;
d1 = d2;
n1 = n0.plus(q.times(d2 = n1));
n0 = d2;
d = n.minus(q.times(d2 = d));
n = d2;
}
d2 = div(md.minus(d0), d1, 0, 1);
n0 = n0.plus(d2.times(n1));
d0 = d0.plus(d2.times(d1));
n0.s = n1.s = x.s;
e *= 2;
// Determine which fraction is closer to x, n0/d0 or n1/d1
arr = div(n1, d1, e, ROUNDING_MODE).minus(x).abs().cmp(
div(n0, d0, e, ROUNDING_MODE).minus(x).abs()) < 1 ? [n1.toString(), d1.toString()] : [n0.toString(), d0.toString()];
MAX_EXP = exp;
return arr;
};
/*
* Return the value of this BigNumber converted to a number primitive.
*/
P.toNumber = function () {
return +this;
};
/*
* Return a BigNumber whose value is the value of this BigNumber raised to the power n.
* If m is present, return the result modulo m.
* If n is negative round according to DECIMAL_PLACES and ROUNDING_MODE.
* If POW_PRECISION is non-zero and m is not present, round to POW_PRECISION using
* ROUNDING_MODE.
*
* The modular power operation works efficiently when x, n, and m are positive integers,
* otherwise it is equivalent to calculating x.toPower(n).modulo(m) (with POW_PRECISION 0).
*
* n {number} Integer, -MAX_SAFE_INTEGER to MAX_SAFE_INTEGER inclusive.
* [m] {number|string|BigNumber} The modulus.
*
* 'pow() exponent not an integer: {n}'
* 'pow() exponent out of range: {n}'
*
* Performs 54 loop iterations for n of 9007199254740991.
*/
P.toPower = P.pow = function (n, m) {
var k, y, z,
i = mathfloor(n < 0 ? -n : +n),
x = this;
if (m != null) {
id = 23;
m = new BigNumber(m);
}
// Pass ±Infinity to Math.pow if exponent is out of range.
if (!isValidInt(n, -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER, 23, 'exponent') &&
(!isFinite(n) || i > MAX_SAFE_INTEGER && (n /= 0) ||
parseFloat(n) != n && !(n = NaN)) || n == 0) {
k = Math.pow(+x, n);
return new BigNumber(m ? k % m : k);
}
if (m) {
if (n > 1 && x.gt(ONE) && x.isInt() && m.gt(ONE) && m.isInt()) {
x = x.mod(m);
} else {
z = m;
// Nullify m so only a single mod operation is performed at the end.
m = null;
}
} else if (POW_PRECISION) {
// Truncating each coefficient array to a length of k after each multiplication
// equates to truncating significant digits to POW_PRECISION + [28, 41],
// i.e. there will be a minimum of 28 guard digits retained.
// (Using + 1.5 would give [9, 21] guard digits.)
k = mathceil(POW_PRECISION / LOG_BASE + 2);
}
y = new BigNumber(ONE);
for (;;) {
if (i % 2) {
y = y.times(x);
if (!y.c) break;
if (k) {
if (y.c.length > k) y.c.length = k;
} else if (m) {
y = y.mod(m);
}
}
i = mathfloor(i / 2);
if (!i) break;
x = x.times(x);
if (k) {
if (x.c && x.c.length > k) x.c.length = k;
} else if (m) {
x = x.mod(m);
}
}
if (m) return y;
if (n < 0) y = ONE.div(y);
return z ? y.mod(z) : k ? round(y, POW_PRECISION, ROUNDING_MODE) : y;
};
/*
* Return a string representing the value of this BigNumber rounded to sd significant digits
* using rounding mode rm or ROUNDING_MODE. If sd is less than the number of digits
* necessary to represent the integer part of the value in fixed-point notation, then use
* exponential notation.
*
* [sd] {number} Significant digits. Integer, 1 to MAX inclusive.
* [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
*
* 'toPrecision() precision not an integer: {sd}'
* 'toPrecision() precision out of range: {sd}'
* 'toPrecision() rounding mode not an integer: {rm}'
* 'toPrecision() rounding mode out of range: {rm}'
*/
P.toPrecision = function (sd, rm) {
return format(this, sd != null && isValidInt(sd, 1, MAX, 24, 'precision') ?
sd | 0 : null, rm, 24);
};
/*
* Return a string representing the value of this BigNumber in base b, or base 10 if b is
* omitted. If a base is specified, including base 10, round according to DECIMAL_PLACES and
* ROUNDING_MODE. If a base is not specified, and this BigNumber has a positive exponent
* that is equal to or greater than TO_EXP_POS, or a negative exponent equal to or less than
* TO_EXP_NEG, return exponential notation.
*
* [b] {number} Integer, 2 to 64 inclusive.
*
* 'toString() base not an integer: {b}'
* 'toString() base out of range: {b}'
*/
P.toString = function (b) {
var str,
n = this,
s = n.s,
e = n.e;
// Infinity or NaN?
if (e === null) {
if (s) {
str = 'Infinity';
if (s < 0) str = '-' + str;
} else {
str = 'NaN';
}
} else {
str = coeffToString(n.c);
if (b == null || !isValidInt(b, 2, 64, 25, 'base')) {
str = e <= TO_EXP_NEG || e >= TO_EXP_POS ?
toExponential(str, e) :
toFixedPoint(str, e);
} else {
str = convertBase(toFixedPoint(str, e), b | 0, 10, s);
}
if (s < 0 && n.c[0]) str = '-' + str;
}
return str;
};
/*
* Return a new BigNumber whose value is the value of this BigNumber truncated to a whole
* number.
*/
P.truncated = P.trunc = function () {
return round(new BigNumber(this), this.e + 1, 1);
};
/*
* Return as toString, but do not accept a base argument, and include the minus sign for
* negative zero.
*/
P.valueOf = P.toJSON = function () {
var str,
n = this,
e = n.e;
if (e === null) return n.toString();
str = coeffToString(n.c);
str = e <= TO_EXP_NEG || e >= TO_EXP_POS ?
toExponential(str, e) :
toFixedPoint(str, e);
return n.s < 0 ? '-' + str : str;
};
P.isBigNumber = true;
if (config != null) BigNumber.config(config);
return BigNumber;
}
// PRIVATE HELPER FUNCTIONS
function bitFloor(n) {
var i = n | 0;
return n > 0 || n === i ? i : i - 1;
}
// Return a coefficient array as a string of base 10 digits.
function coeffToString(a) {
var s, z,
i = 1,
j = a.length,
r = a[0] + '';
for (; i < j;) {
s = a[i++] + '';
z = LOG_BASE - s.length;
for (; z--; s = '0' + s);
r += s;
}
// Determine trailing zeros.
for (j = r.length; r.charCodeAt(--j) === 48;);
return r.slice(0, j + 1 || 1);
}
// Compare the value of BigNumbers x and y.
function compare(x, y) {
var a, b,
xc = x.c,
yc = y.c,
i = x.s,
j = y.s,
k = x.e,
l = y.e;
// Either NaN?
if (!i || !j) return null;
a = xc && !xc[0];
b = yc && !yc[0];
// Either zero?
if (a || b) return a ? b ? 0 : -j : i;
// Signs differ?
if (i != j) return i;
a = i < 0;
b = k == l;
// Either Infinity?
if (!xc || !yc) return b ? 0 : !xc ^ a ? 1 : -1;
// Compare exponents.
if (!b) return k > l ^ a ? 1 : -1;
j = (k = xc.length) < (l = yc.length) ? k : l;
// Compare digit by digit.
for (i = 0; i < j; i++)
if (xc[i] != yc[i]) return xc[i] > yc[i] ^ a ? 1 : -1;
// Compare lengths.
return k == l ? 0 : k > l ^ a ? 1 : -1;
}
/*
* Return true if n is a valid number in range, otherwise false.
* Use for argument validation when ERRORS is false.
* Note: parseInt('1e+1') == 1 but parseFloat('1e+1') == 10.
*/
function intValidatorNoErrors(n, min, max) {
return (n = truncate(n)) >= min && n <= max;
}
function isArray(obj) {
return Object.prototype.toString.call(obj) == '[object Array]';
}
/*
* Convert string of baseIn to an array of numbers of baseOut.
* Eg. convertBase('255', 10, 16) returns [15, 15].
* Eg. convertBase('ff', 16, 10) returns [2, 5, 5].
*/
function toBaseOut(str, baseIn, baseOut) {
var j,
arr = [0],
arrL,
i = 0,
len = str.length;
for (; i < len;) {
for (arrL = arr.length; arrL--; arr[arrL] *= baseIn);
arr[j = 0] += ALPHABET.indexOf(str.charAt(i++));
for (; j < arr.length; j++) {
if (arr[j] > baseOut - 1) {
if (arr[j + 1] == null) arr[j + 1] = 0;
arr[j + 1] += arr[j] / baseOut | 0;
arr[j] %= baseOut;
}
}
}
return arr.reverse();
}
function toExponential(str, e) {
return (str.length > 1 ? str.charAt(0) + '.' + str.slice(1) : str) +
(e < 0 ? 'e' : 'e+') + e;
}
function toFixedPoint(str, e) {
var len, z;
// Negative exponent?
if (e < 0) {
// Prepend zeros.
for (z = '0.'; ++e; z += '0');
str = z + str;
// Positive exponent
} else {
len = str.length;
// Append zeros.
if (++e > len) {
for (z = '0', e -= len; --e; z += '0');
str += z;
} else if (e < len) {
str = str.slice(0, e) + '.' + str.slice(e);
}
}
return str;
}
function truncate(n) {
n = parseFloat(n);
return n < 0 ? mathceil(n) : mathfloor(n);
}
BigNumber = constructorFactory();
BigNumber['default'] = BigNumber.BigNumber = BigNumber;
function json_parse(options) {
"use strict";
var _options = {
"strict": false, // not being strict means do not generate syntax errors for "duplicate key"
"storeAsString": false // toggles whether the values should be stored as BigNumber (default) or a string
};
// If there are options, then use them to override the default _options
if (options !== undefined && options !== null) {
if (options.strict === true) {
_options.strict = true;
}
if (options.storeAsString === true) {
_options.storeAsString = true;
}
}
var at, // The index of the current character
ch, // The current character
escapee = {
'"': '"',
'\\': '\\',
'/': '/',
b: '\b',
f: '\f',
n: '\n',
r: '\r',
t: '\t'
},
text,
error = function (m) {
// Call error when something is wrong.
throw {
name: 'SyntaxError',
message: m,
at: at,
text: text
};
},
next = function (c) {
// If a c parameter is provided, verify that it matches the current character.
if (c && c !== ch) {
error("Expected '" + c + "' instead of '" + ch + "'");
}
// Get the next character. When there are no more characters,
// return the empty string.
ch = text.charAt(at);
at += 1;
return ch;
},
number = function () {
// Parse a number value.
var number,
string = '';
if (ch === '-') {
string = '-';
next('-');
}
while (ch >= '0' && ch <= '9') {
string += ch;
next();
}
if (ch === '.') {
string += '.';
while (next() && ch >= '0' && ch <= '9') {
string += ch;
}
}
if (ch === 'e' || ch === 'E') {
string += ch;
next();
if (ch === '-' || ch === '+') {
string += ch;
next();
}
while (ch >= '0' && ch <= '9') {
string += ch;
next();
}
}
number = +string;
if (!isFinite(number)) {
error("Bad number");
} else {
if (BigNumber == null)
BigNumber = require('bignumber.js');
//if (number > 9007199254740992 || number < -9007199254740992)
// Bignumber has stricter check: everything with length > 15 digits disallowed
if (string.length > 15)
return (_options.storeAsString === true) ? string : new BigNumber(string);
return number;
}
},
string = function () {
// Parse a string value.
var hex,
i,
string = '',
uffff;
// When parsing for string values, we must look for " and \ characters.
if (ch === '"') {
while (next()) {
if (ch === '"') {
next();
return string;
}
if (ch === '\\') {
next();
if (ch === 'u') {
uffff = 0;
for (i = 0; i < 4; i += 1) {
hex = parseInt(next(), 16);
if (!isFinite(hex)) {
break;
}
uffff = uffff * 16 + hex;
}
string += String.fromCharCode(uffff);
} else if (typeof escapee[ch] === 'string') {
string += escapee[ch];
} else {
break;
}
} else {
string += ch;
}
}
}
error("Bad string");
},
white = function () {
// Skip whitespace.
while (ch && ch <= ' ') {
next();
}
},
word = function () {
// true, false, or null.
switch (ch) {
case 't':
next('t');
next('r');
next('u');
next('e');
return true;
case 'f':
next('f');
next('a');
next('l');
next('s');
next('e');
return false;
case 'n':
next('n');
next('u');
next('l');
next('l');
return null;
}
error("Unexpected '" + ch + "'");
},
value, // Place holder for the value function.
array = function () {
// Parse an array value.
var array = [];
if (ch === '[') {
next('[');
white();
if (ch === ']') {
next(']');
return array; // empty array
}
while (ch) {
array.push(value());
white();
if (ch === ']') {
next(']');
return array;
}
next(',');
white();
}
}
error("Bad array");
},
object = function () {
// Parse an object value.
var key,
object = {};
if (ch === '{') {
next('{');
white();
if (ch === '}') {
next('}');
return object; // empty object
}
while (ch) {
key = string();
white();
next(':');
if (_options.strict === true && Object.hasOwnProperty.call(object, key)) {
error('Duplicate key "' + key + '"');
}
object[key] = value();
white();
if (ch === '}') {
next('}');
return object;
}
next(',');
white();
}
}
error("Bad object");
};
value = function () {
// Parse a JSON value. It could be an object, an array, a string, a number,
// or a word.
white();
switch (ch) {
case '{':
return object();
case '[':
return array();
case '"':
return string();
case '-':
return number();
default:
return ch >= '0' && ch <= '9' ? number() : word();
}
};
// Return the json_parse function. It will have access to all of the above
// functions and variables.
return function (source, reviver) {
var result;
text = source + '';
at = 0;
ch = ' ';
result = value();
white();
if (ch) {
error("Syntax error");
}
return typeof reviver === 'function' ?
(function walk(holder, key) {
var k, v, value = holder[key];
if (value && typeof value === 'object') {
Object.keys(value).forEach(function (k) {
v = walk(value, k);
if (v !== undefined) {
value[k] = v;
} else {
delete value[k];
}
});
}
return reviver.call(holder, key, value);
}({
'': result
}, '')) :
result;
};
}
var jso = {}
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
gap,
indent,
meta = { // table of character substitutions
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"': '\\"',
'\\': '\\\\'
},
rep;
function quote(string) {
// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.
escapable.lastIndex = 0;
return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
var c = meta[a];
return typeof c === 'string' ?
c :
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
}) + '"' : '"' + string + '"';
}
function str(key, holder) {
// Produce a string from holder[key].
var i, // The loop counter.
k, // The member key.
v, // The member value.
length,
mind = gap,
partial,
value = holder[key],
isBigNumber = value != null && (value instanceof BigNumber || value.isBigNumber);;
// If the value has a toJSON method, call it to obtain a replacement value.
if (value && typeof value === 'object' &&
typeof value.toJSON === 'function') {
value = value.toJSON(key);
}
// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.
if (typeof rep === 'function') {
value = rep.call(holder, key, value);
}
// What happens next depends on the value's type.
switch (typeof value) {
case 'string':
if (isBigNumber) {
return value;
} else {
return quote(value);
}
case 'number':
// JSON numbers must be finite. Encode non-finite numbers as null.
return isFinite(value) ? String(value) : 'null';
case 'boolean':
case 'null':
// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce 'null'. The case is included here in
// the remote chance that this gets fixed someday.
return String(value);
// If the type is 'object', we might be dealing with an object or an array or
// null.
case 'object':
// Due to a specification blunder in ECMAScript, typeof null is 'object',
// so watch out for that case.
if (!value) {
return 'null';
}
// Make an array to hold the partial results of stringifying this object value.
gap += indent;
partial = [];
// Is the value an array?
if (Object.prototype.toString.apply(value) === '[object Array]') {
// The value is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.
length = value.length;
for (i = 0; i < length; i += 1) {
partial[i] = str(i, value) || 'null';
}
// Join all of the elements together, separated with commas, and wrap them in
// brackets.
v = partial.length === 0 ?
'[]' :
gap ?
'[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
'[' + partial.join(',') + ']';
gap = mind;
return v;
}
// If the replacer is an array, use it to select the members to be stringified.
if (rep && typeof rep === 'object') {
length = rep.length;
for (i = 0; i < length; i += 1) {
if (typeof rep[i] === 'string') {
k = rep[i];
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
} else {
// Otherwise, iterate through all of the keys in the object.
Object.keys(value).forEach(function (k) {
var v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
});
}
// Join all of the member texts together, separated with commas,
// and wrap them in braces.
v = partial.length === 0 ?
'{}' :
gap ?
'{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
'{' + partial.join(',') + '}';
gap = mind;
return v;
}
}
// If the JSON object does not yet have a stringify method, give it one.
jso.stringify = function (value, replacer, space) {
// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.
var i;
gap = '';
indent = '';
// If the space parameter is a number, make an indent string containing that
// many spaces.
if (typeof space === 'number') {
for (i = 0; i < space; i += 1) {
indent += ' ';
}
// If the space parameter is a string, it will be used as the indent string.
} else if (typeof space === 'string') {
indent = space;
}
// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.
rep = replacer;
if (replacer && typeof replacer !== 'function' &&
(typeof replacer !== 'object' ||
typeof replacer.length !== 'number')) {
throw new Error('JSON.stringify');
}
// Make a fake root object containing our value under the key of ''.
// Return the result of stringifying the value.
return str('', {
'': value
});
};
jso.get = function (options) {
return {
parse: json_parse(options),
stringify: jso.stringify
}
}
var JSON = jso.get();
function constructorFactory(e){function t(e,r){var o,i,u,c,g,h,S=this;if(!(S instanceof t))return B&&f(26,"constructor call without new",e),new t(e,r);if(null!=r&&b(r,2,64,a,"base")){if(r=0|r,h=e+"",10==r)return S=new t(e instanceof t?e:h),s(S,p+S.e+1,A);if((c="number"==typeof e)&&0*e!=0||!new RegExp("^-?"+(o="["+ALPHABET.slice(0,r)+"]+")+"(?:\\."+o+")?$",37>r?"i":"").test(h))return l(S,h,c,r);c?(S.s=0>1/e?(h=h.slice(1),-1):1,B&&h.replace(/^0\.0*|\./,"").length>15&&f(a,tooManyDigits,e),c=!1):S.s=45===h.charCodeAt(0)?(h=h.slice(1),-1):1,h=n(h,10,r,S.s)}else{if(e instanceof t)return S.s=e.s,S.e=e.e,S.c=(e=e.c)?e.slice():e,void(a=0);if((c="number"==typeof e)&&0*e==0){if(S.s=0>1/e?(e=-e,-1):1,e===~~e){for(i=0,u=e;u>=10;u/=10,i++);return S.e=i,S.c=[e],void(a=0)}h=e+""}else{if(!isNumeric.test(h=e+""))return l(S,h,c);S.s=45===h.charCodeAt(0)?(h=h.slice(1),-1):1}}for((i=h.indexOf("."))>-1&&(h=h.replace(".","")),(u=h.search(/e/i))>0?(0>i&&(i=u),i+=+h.slice(u+1),h=h.substring(0,u)):0>i&&(i=h.length),u=0;48===h.charCodeAt(u);u++);for(g=h.length;48===h.charCodeAt(--g););if(h=h.slice(u,g+1))if(g=h.length,c&&B&&g>15&&(e>MAX_SAFE_INTEGER||e!==mathfloor(e))&&f(a,tooManyDigits,S.s*e),i=i-u-1,i>d)S.c=S.e=null;else if(m>i)S.c=[S.e=0];else{if(S.e=i,S.c=[],u=(i+1)%LOG_BASE,0>i&&(u+=LOG_BASE),g>u){for(u&&S.c.push(+h.slice(0,u)),g-=LOG_BASE;g>u;)S.c.push(+h.slice(u,u+=LOG_BASE));h=h.slice(u),u=LOG_BASE-h.length}else u-=g;for(;u--;h+="0");S.c.push(+h)}else S.c=[S.e=0];a=0}function n(e,n,r,o){var i,u,f,s,l,a,g,h=e.indexOf("."),S=p,E=A;for(37>r&&(e=e.toLowerCase()),h>=0&&(f=v,v=0,e=e.replace(".",""),g=new t(r),l=g.pow(e.length-h),v=f,g.c=toBaseOut(toFixedPoint(coeffToString(l.c),l.e),10,n),g.e=g.c.length),a=toBaseOut(e,r,n),u=f=a.length;0==a[--f];a.pop());if(!a[0])return"0";if(0>h?--u:(l.c=a,l.e=u,l.s=o,l=c(l,g,S,E,n),a=l.c,s=l.r,u=l.e),i=u+S+1,h=a[i],f=n/2,s=s||0>i||null!=a[i+1],s=4>E?(null!=h||s)&&(0==E||E==(l.s<0?3:2)):h>f||h==f&&(4==E||s||6==E&&1&a[i-1]||E==(l.s<0?8:7)),1>i||!a[0])e=s?toFixedPoint("1",-S):"0";else{if(a.length=i,s)for(--n;++a[--i]>n;)a[i]=0,i||(++u,a=[1].concat(a));for(f=a.length;!a[--f];);for(h=0,e="";f>=h;e+=ALPHABET.charAt(a[h++]));e=toFixedPoint(e,u)}return e}function r(e,n,r,o){var i,u,f,c,l;if(r=null!=r&&b(r,0,8,o,roundingMode)?0|r:A,!e.c)return e.toString();if(i=e.c[0],f=e.e,null==n)l=coeffToString(e.c),l=19==o||24==o&&S>=f?toExponential(l,f):toFixedPoint(l,f);else if(e=s(new t(e),n,r),u=e.e,l=coeffToString(e.c),c=l.length,19==o||24==o&&(u>=n||S>=u)){for(;n>c;l+="0",c++);l=toExponential(l,u)}else if(n-=f,l=toFixedPoint(l,u),u+1>c){if(--n>0)for(l+=".";n--;l+="0");}else if(n+=u-c,n>0)for(u+1==c&&(l+=".");n--;l+="0");return e.s<0&&i?"-"+l:l}function o(e,n){var r,o,i=0;for(isArray(e[0])&&(e=e[0]),r=new t(e[0]);++i<e.length;){if(o=new t(e[i]),!o.s){r=o;break}n.call(r,o)&&(r=o)}return r}function i(e,t,n,r,o){return(t>e||e>n||e!=truncate(e))&&f(r,(o||"decimal places")+(t>e||e>n?" out of range":" not an integer"),e),!0}function u(e,t,n){for(var r=1,o=t.length;!t[--o];t.pop());for(o=t[0];o>=10;o/=10,r++);return(n=r+n*LOG_BASE-1)>d?e.c=e.e=null:m>n?e.c=[e.e=0]:(e.e=n,e.c=t),e}function f(e,t,n){var r=new Error(["new BigNumber","cmp","config","div","divToInt","eq","gt","gte","lt","lte","minus","mod","plus","precision","random","round","shift","times","toDigits","toExponential","toFixed","toFormat","toFraction","pow","toPrecision","toString","BigNumber"][e]+"() "+t+": "+n);throw r.name="BigNumber Error",a=0,r}function s(e,t,n,r){var o,i,u,f,s,c,l,a=e.c,g=POWS_TEN;if(a){e:{for(o=1,f=a[0];f>=10;f/=10,o++);if(i=t-o,0>i)i+=LOG_BASE,u=t,s=a[c=0],l=s/g[o-u-1]%10|0;else if(c=mathceil((i+1)/LOG_BASE),c>=a.length){if(!r)break e;for(;a.length<=c;a.push(0));s=l=0,o=1,i%=LOG_BASE,u=i-LOG_BASE+1}else{for(s=f=a[c],o=1;f>=10;f/=10,o++);i%=LOG_BASE,u=i-LOG_BASE+o,l=0>u?0:s/g[o-u-1]%10|0}if(r=r||0>t||null!=a[c+1]||(0>u?s:s%g[o-u-1]),r=4>n?(l||r)&&(0==n||n==(e.s<0?3:2)):l>5||5==l&&(4==n||r||6==n&&(i>0?u>0?s/g[o-u]:0:a[c-1])%10&1||n==(e.s<0?8:7)),1>t||!a[0])return a.length=0,r?(t-=e.e+1,a[0]=g[(LOG_BASE-t%LOG_BASE)%LOG_BASE],e.e=-t||0):a[0]=e.e=0,e;if(0==i?(a.length=c,f=1,c--):(a.length=c+1,f=g[LOG_BASE-i],a[c]=u>0?mathfloor(s/g[o-u]%g[u])*f:0),r)for(;;){if(0==c){for(i=1,u=a[0];u>=10;u/=10,i++);for(u=a[0]+=f,f=1;u>=10;u/=10,f++);i!=f&&(e.e++,a[0]==BASE&&(a[0]=1));break}if(a[c]+=f,a[c]!=BASE)break;a[c--]=0,f=1}for(i=a.length;0===a[--i];a.pop());}e.e>d?e.c=e.e=null:e.e<m&&(e.c=[e.e=0])}return e}var c,l,a=0,g=t.prototype,h=new t(1),p=20,A=4,S=-7,E=21,m=-1e7,d=1e7,B=!0,b=i,O=!1,_=1,v=0,w={decimalSeparator:".",groupSeparator:",",groupSize:3,secondaryGroupSize:0,fractionGroupSeparator:" ",fractionGroupSize:0};return t.another=constructorFactory,t.ROUND_UP=0,t.ROUND_DOWN=1,t.ROUND_CEIL=2,t.ROUND_FLOOR=3,t.ROUND_HALF_UP=4,t.ROUND_HALF_DOWN=5,t.ROUND_HALF_EVEN=6,t.ROUND_HALF_CEIL=7,t.ROUND_HALF_FLOOR=8,t.EUCLID=9,t.config=t.set=function(){var e,t,n=0,r={},o=arguments,u=o[0],s=u&&"object"==typeof u?function(){return u.hasOwnProperty(t)?null!=(e=u[t]):void 0}:function(){return o.length>n?null!=(e=o[n++]):void 0};return s(t="DECIMAL_PLACES")&&b(e,0,MAX,2,t)&&(p=0|e),r[t]=p,s(t="ROUNDING_MODE")&&b(e,0,8,2,t)&&(A=0|e),r[t]=A,s(t="EXPONENTIAL_AT")&&(isArray(e)?b(e[0],-MAX,0,2,t)&&b(e[1],0,MAX,2,t)&&(S=0|e[0],E=0|e[1]):b(e,-MAX,MAX,2,t)&&(S=-(E=0|(0>e?-e:e)))),r[t]=[S,E],s(t="RANGE")&&(isArray(e)?b(e[0],-MAX,-1,2,t)&&b(e[1],1,MAX,2,t)&&(m=0|e[0],d=0|e[1]):b(e,-MAX,MAX,2,t)&&(0|e?m=-(d=0|(0>e?-e:e)):B&&f(2,t+" cannot be zero",e))),r[t]=[m,d],s(t="ERRORS")&&(e===!!e||1===e||0===e?(a=0,b=(B=!!e)?i:intValidatorNoErrors):B&&f(2,t+notBool,e)),r[t]=B,s(t="CRYPTO")&&(e===!0||e===!1||1===e||0===e?e?(e="undefined"==typeof crypto,!e&&crypto&&(crypto.getRandomValues||crypto.randomBytes)?O=!0:B?f(2,"crypto unavailable",e?void 0:crypto):O=!1):O=!1:B&&f(2,t+notBool,e)),r[t]=O,s(t="MODULO_MODE")&&b(e,0,9,2,t)&&(_=0|e),r[t]=_,s(t="POW_PRECISION")&&b(e,0,MAX,2,t)&&(v=0|e),r[t]=v,s(t="FORMAT")&&("object"==typeof e?w=e:B&&f(2,t+" not an object",e)),r[t]=w,r},t.max=function(){return o(arguments,g.lt)},t.min=function(){return o(arguments,g.gt)},t.random=function(){var e=9007199254740992,n=Math.random()*e&2097151?function(){return mathfloor(Math.random()*e)}:function(){return 8388608*(1073741824*Math.random()|0)+(8388608*Math.random()|0)};return function(e){var r,o,i,u,s,c=0,l=[],a=new t(h);if(e=null!=e&&b(e,0,MAX,14)?0|e:p,u=mathceil(e/LOG_BASE),O)if(crypto.getRandomValues){for(r=crypto.getRandomValues(new Uint32Array(u*=2));u>c;)s=131072*r[c]+(r[c+1]>>>11),s>=9e15?(o=crypto.getRandomValues(new Uint32Array(2)),r[c]=o[0],r[c+1]=o[1]):(l.push(s%1e14),c+=2);c=u/2}else if(crypto.randomBytes){for(r=crypto.randomBytes(u*=7);u>c;)s=281474976710656*(31&r[c])+1099511627776*r[c+1]+4294967296*r[c+2]+16777216*r[c+3]+(r[c+4]<<16)+(r[c+5]<<8)+r[c+6],s>=9e15?crypto.randomBytes(7).copy(r,c):(l.push(s%1e14),c+=7);c=u/7}else O=!1,B&&f(14,"crypto unavailable",crypto);if(!O)for(;u>c;)s=n(),9e15>s&&(l[c++]=s%1e14);for(u=l[--c],e%=LOG_BASE,u&&e&&(s=POWS_TEN[LOG_BASE-e],l[c]=mathfloor(u/s)*s);0===l[c];l.pop(),c--);if(0>c)l=[i=0];else{for(i=-1;0===l[0];l.splice(0,1),i-=LOG_BASE);for(c=1,s=l[0];s>=10;s/=10,c++);LOG_BASE>c&&(i-=LOG_BASE-c)}return a.e=i,a.c=l,a}}(),c=function(){function e(e,t,n){var r,o,i,u,f=0,s=e.length,c=t%SQRT_BASE,l=t/SQRT_BASE|0;for(e=e.slice();s--;)i=e[s]%SQRT_BASE,u=e[s]/SQRT_BASE|0,r=l*i+u*c,o=c*i+r%SQRT_BASE*SQRT_BASE+f,f=(o/n|0)+(r/SQRT_BASE|0)+l*u,e[s]=o%n;return f&&(e=[f].concat(e)),e}function n(e,t,n,r){var o,i;if(n!=r)i=n>r?1:-1;else for(o=i=0;n>o;o++)if(e[o]!=t[o]){i=e[o]>t[o]?1:-1;break}return i}function r(e,t,n,r){for(var o=0;n--;)e[n]-=o,o=e[n]<t[n]?1:0,e[n]=o*r+e[n]-t[n];for(;!e[0]&&e.length>1;e.splice(0,1));}return function(o,i,u,f,c){var l,a,g,h,p,A,S,E,m,d,B,b,O,_,v,w,N,y=o.s==i.s?1:-1,L=o.c,G=i.c;if(!(L&&L[0]&&G&&G[0]))return new t(o.s&&i.s&&(L?!G||L[0]!=G[0]:G)?L&&0==L[0]||!G?0*y:y/0:NaN);for(E=new t(y),m=E.c=[],a=o.e-i.e,y=u+a+1,c||(c=BASE,a=bitFloor(o.e/LOG_BASE)-bitFloor(i.e/LOG_BASE),y=y/LOG_BASE|0),g=0;G[g]==(L[g]||0);g++);if(G[g]>(L[g]||0)&&a--,0>y)m.push(1),h=!0;else{for(_=L.length,w=G.length,g=0,y+=2,p=mathfloor(c/(G[0]+1)),p>1&&(G=e(G,p,c),L=e(L,p,c),w=G.length,_=L.length),O=w,d=L.slice(0,w),B=d.length;w>B;d[B++]=0);N=G.slice(),N=[0].concat(N),v=G[0],G[1]>=c/2&&v++;do{if(p=0,l=n(G,d,w,B),0>l){if(b=d[0],w!=B&&(b=b*c+(d[1]||0)),p=mathfloor(b/v),p>1)for(p>=c&&(p=c-1),A=e(G,p,c),S=A.length,B=d.length;1==n(A,d,S,B);)p--,r(A,S>w?N:G,S,c),S=A.length,l=1;else 0==p&&(l=p=1),A=G.slice(),S=A.length;if(B>S&&(A=[0].concat(A)),r(d,A,B,c),B=d.length,-1==l)for(;n(G,d,w,B)<1;)p++,r(d,B>w?N:G,B,c),B=d.length}else 0===l&&(p++,d=[0]);m[g++]=p,d[0]?d[B++]=L[O]||0:(d=[L[O]],B=1)}while((O++<_||null!=d[0])&&y--);h=null!=d[0],m[0]||m.splice(0,1)}if(c==BASE){for(g=1,y=m[0];y>=10;y/=10,g++);s(E,u+(E.e=g+a*LOG_BASE-1)+1,f,h)}else E.e=a,E.r=+h;return E}}(),l=function(){var e=/^(-?)0([xbo])(?=\w[\w.]*$)/i,n=/^([^.]+)\.$/,r=/^\.([^.]+)$/,o=/^-?(Infinity|NaN)$/,i=/^\s*\+(?=[\w.])|^\s+|\s+$/g;return function(u,s,c,l){var g,h=c?s:s.replace(i,"");if(o.test(h))u.s=isNaN(h)?null:0>h?-1:1;else{if(!c&&(h=h.replace(e,function(e,t,n){return g="x"==(n=n.toLowerCase())?16:"b"==n?2:8,l&&l!=g?e:t}),l&&(g=l,h=h.replace(n,"$1").replace(r,"0.$1")),s!=h))return new t(h,g);B&&f(a,"not a"+(l?" base "+l:"")+" number",s),u.s=null}u.c=u.e=null,a=0}}(),g.absoluteValue=g.abs=function(){var e=new t(this);return e.s<0&&(e.s=1),e},g.ceil=function(){return s(new t(this),this.e+1,2)},g.comparedTo=g.cmp=function(e,n){return a=1,compare(this,new t(e,n))},g.decimalPlaces=g.dp=function(){var e,t,n=this.c;if(!n)return null;if(e=((t=n.length-1)-bitFloor(this.e/LOG_BASE))*LOG_BASE,t=n[t])for(;t%10==0;t/=10,e--);return 0>e&&(e=0),e},g.dividedBy=g.div=function(e,n){return a=3,c(this,new t(e,n),p,A)},g.dividedToIntegerBy=g.divToInt=function(e,n){return a=4,c(this,new t(e,n),0,1)},g.equals=g.eq=function(e,n){return a=5,0===compare(this,new t(e,n))},g.floor=function(){return s(new t(this),this.e+1,3)},g.greaterThan=g.gt=function(e,n){return a=6,compare(this,new t(e,n))>0},g.greaterThanOrEqualTo=g.gte=function(e,n){return a=7,1===(n=compare(this,new t(e,n)))||0===n},g.isFinite=function(){return!!this.c},g.isInteger=g.isInt=function(){return!!this.c&&bitFloor(this.e/LOG_BASE)>this.c.length-2},g.isNaN=function(){return!this.s},g.isNegative=g.isNeg=function(){return this.s<0},g.isZero=function(){return!!this.c&&0==this.c[0]},g.lessThan=g.lt=function(e,n){return a=8,compare(this,new t(e,n))<0},g.lessThanOrEqualTo=g.lte=function(e,n){return a=9,-1===(n=compare(this,new t(e,n)))||0===n},g.minus=g.sub=function(e,n){var r,o,i,f,s=this,c=s.s;if(a=10,e=new t(e,n),n=e.s,!c||!n)return new t(NaN);if(c!=n)return e.s=-n,s.plus(e);var l=s.e/LOG_BASE,g=e.e/LOG_BASE,h=s.c,p=e.c;if(!l||!g){if(!h||!p)return h?(e.s=-n,e):new t(p?s:NaN);if(!h[0]||!p[0])return p[0]?(e.s=-n,e):new t(h[0]?s:3==A?-0:0)}if(l=bitFloor(l),g=bitFloor(g),h=h.slice(),c=l-g){for((f=0>c)?(c=-c,i=h):(g=l,i=p),i.reverse(),n=c;n--;i.push(0));i.reverse()}else for(o=(f=(c=h.length)<(n=p.length))?c:n,c=n=0;o>n;n++)if(h[n]!=p[n]){f=h[n]<p[n];break}if(f&&(i=h,h=p,p=i,e.s=-e.s),n=(o=p.length)-(r=h.length),n>0)for(;n--;h[r++]=0);for(n=BASE-1;o>c;){if(h[--o]<p[o]){for(r=o;r&&!h[--r];h[r]=n);--h[r],h[o]+=BASE}h[o]-=p[o]}for(;0==h[0];h.splice(0,1),--g);return h[0]?u(e,h,g):(e.s=3==A?-1:1,e.c=[e.e=0],e)},g.modulo=g.mod=function(e,n){var r,o,i=this;return a=11,e=new t(e,n),!i.c||!e.s||e.c&&!e.c[0]?new t(NaN):!e.c||i.c&&!i.c[0]?new t(i):(9==_?(o=e.s,e.s=1,r=c(i,e,0,3),e.s=o,r.s*=o):r=c(i,e,0,_),i.minus(r.times(e)))},g.negated=g.neg=function(){var e=new t(this);return e.s=-e.s||null,e},g.plus=g.add=function(e,n){var r,o=this,i=o.s;if(a=12,e=new t(e,n),n=e.s,!i||!n)return new t(NaN);if(i!=n)return e.s=-n,o.minus(e);var f=o.e/LOG_BASE,s=e.e/LOG_BASE,c=o.c,l=e.c;if(!f||!s){if(!c||!l)return new t(i/0);if(!c[0]||!l[0])return l[0]?e:new t(c[0]?o:0*i)}if(f=bitFloor(f),s=bitFloor(s),c=c.slice(),i=f-s){for(i>0?(s=f,r=l):(i=-i,r=c),r.reverse();i--;r.push(0));r.reverse()}for(i=c.length,n=l.length,0>i-n&&(r=l,l=c,c=r,n=i),i=0;n;)i=(c[--n]=c[n]+l[n]+i)/BASE|0,c[n]=BASE===c[n]?0:c[n]%BASE;return i&&(c=[i].concat(c),++s),u(e,c,s)},g.precision=g.sd=function(e){var t,n,r=this,o=r.c;if(null!=e&&e!==!!e&&1!==e&&0!==e&&(B&&f(13,"argument"+notBool,e),e!=!!e&&(e=null)),!o)return null;if(n=o.length-1,t=n*LOG_BASE+1,n=o[n]){for(;n%10==0;n/=10,t--);for(n=o[0];n>=10;n/=10,t++);}return e&&r.e+1>t&&(t=r.e+1),t},g.round=function(e,n){var r=new t(this);return(null==e||b(e,0,MAX,15))&&s(r,~~e+this.e+1,null!=n&&b(n,0,8,15,roundingMode)?0|n:A),r},g.shift=function(e){var n=this;return b(e,-MAX_SAFE_INTEGER,MAX_SAFE_INTEGER,16,"argument")?n.times("1e"+truncate(e)):new t(n.c&&n.c[0]&&(-MAX_SAFE_INTEGER>e||e>MAX_SAFE_INTEGER)?n.s*(0>e?0:1/0):n)},g.squareRoot=g.sqrt=function(){var e,n,r,o,i,u=this,f=u.c,l=u.s,a=u.e,g=p+4,h=new t("0.5");if(1!==l||!f||!f[0])return new t(!l||0>l&&(!f||f[0])?NaN:f?u:1/0);if(l=Math.sqrt(+u),0==l||l==1/0?(n=coeffToString(f),(n.length+a)%2==0&&(n+="0"),l=Math.sqrt(n),a=bitFloor((a+1)/2)-(0>a||a%2),l==1/0?n="1e"+a:(n=l.toExponential(),n=n.slice(0,n.indexOf("e")+1)+a),r=new t(n)):r=new t(l+""),r.c[0])for(a=r.e,l=a+g,3>l&&(l=0);;)if(i=r,r=h.times(i.plus(c(u,i,g,1))),coeffToString(i.c).slice(0,l)===(n=coeffToString(r.c)).slice(0,l)){if(r.e<a&&--l,n=n.slice(l-3,l+1),"9999"!=n&&(o||"4999"!=n)){(!+n||!+n.slice(1)&&"5"==n.charAt(0))&&(s(r,r.e+p+2,1),e=!r.times(r).eq(u));break}if(!o&&(s(i,i.e+p+2,0),i.times(i).eq(u))){r=i;break}g+=4,l+=4,o=1}return s(r,r.e+p+1,A,e)},g.times=g.mul=function(e,n){var r,o,i,f,s,c,l,g,h,p,A,S,E,m,d,B=this,b=B.c,O=(a=17,e=new t(e,n)).c;if(!(b&&O&&b[0]&&O[0]))return!B.s||!e.s||b&&!b[0]&&!O||O&&!O[0]&&!b?e.c=e.e=e.s=null:(e.s*=B.s,b&&O?(e.c=[0],e.e=0):e.c=e.e=null),e;for(o=bitFloor(B.e/LOG_BASE)+bitFloor(e.e/LOG_BASE),e.s*=B.s,l=b.length,p=O.length,p>l&&(E=b,b=O,O=E,i=l,l=p,p=i),i=l+p,E=[];i--;E.push(0));for(m=BASE,d=SQRT_BASE,i=p;--i>=0;){for(r=0,A=O[i]%d,S=O[i]/d|0,s=l,f=i+s;f>i;)g=b[--s]%d,h=b[s]/d|0,c=S*g+h*A,g=A*g+c%d*d+E[f]+r,r=(g/m|0)+(c/d|0)+S*h,E[f--]=g%m;E[f]=r}return r?++o:E.splice(0,1),u(e,E,o)},g.toDigits=function(e,n){var r=new t(this);return e=null!=e&&b(e,1,MAX,18,"precision")?0|e:null,n=null!=n&&b(n,0,8,18,roundingMode)?0|n:A,e?s(r,e,n):r},g.toExponential=function(e,t){return r(this,null!=e&&b(e,0,MAX,19)?~~e+1:null,t,19)},g.toFixed=function(e,t){return r(this,null!=e&&b(e,0,MAX,20)?~~e+this.e+1:null,t,20)},g.toFormat=function(e,t){var n=r(this,null!=e&&b(e,0,MAX,21)?~~e+this.e+1:null,t,21);if(this.c){var o,i=n.split("."),u=+w.groupSize,f=+w.secondaryGroupSize,s=w.groupSeparator,c=i[0],l=i[1],a=this.s<0,g=a?c.slice(1):c,h=g.length;if(f&&(o=u,u=f,f=o,h-=o),u>0&&h>0){for(o=h%u||u,c=g.substr(0,o);h>o;o+=u)c+=s+g.substr(o,u);f>0&&(c+=s+g.slice(o)),a&&(c="-"+c)}n=l?c+w.decimalSeparator+((f=+w.fractionGroupSize)?l.replace(new RegExp("\\d{"+f+"}\\B","g"),"$&"+w.fractionGroupSeparator):l):c}return n},g.toFraction=function(e){var n,r,o,i,u,l,a,g,p,S=B,E=this,m=E.c,b=new t(h),O=r=new t(h),_=a=new t(h);if(null!=e&&(B=!1,l=new t(e),B=S,(!(S=l.isInt())||l.lt(h))&&(B&&f(22,"max denominator "+(S?"out of range":"not an integer"),e),e=!S&&l.c&&s(l,l.e+1,1).gte(h)?l:null)),!m)return E.toString();for(p=coeffToString(m),i=b.e=p.length-E.e-1,b.c[0]=POWS_TEN[(u=i%LOG_BASE)<0?LOG_BASE+u:u],e=!e||l.cmp(b)>0?i>0?b:O:l,u=d,d=1/0,l=new t(p),a.c[0]=0;g=c(l,b,0,1),o=r.plus(g.times(_)),1!=o.cmp(e);)r=_,_=o,O=a.plus(g.times(o=O)),a=o,b=l.minus(g.times(o=b)),l=o;return o=c(e.minus(r),_,0,1),a=a.plus(o.times(O)),r=r.plus(o.times(_)),a.s=O.s=E.s,i*=2,n=c(O,_,i,A).minus(E).abs().cmp(c(a,r,i,A).minus(E).abs())<1?[O.toString(),_.toString()]:[a.toString(),r.toString()],d=u,n},g.toNumber=function(){return+this},g.toPower=g.pow=function(e,n){var r,o,i,u=mathfloor(0>e?-e:+e),f=this;if(null!=n&&(a=23,n=new t(n)),!b(e,-MAX_SAFE_INTEGER,MAX_SAFE_INTEGER,23,"exponent")&&(!isFinite(e)||u>MAX_SAFE_INTEGER&&(e/=0)||parseFloat(e)!=e&&!(e=NaN))||0==e)return r=Math.pow(+f,e),new t(n?r%n:r);for(n?e>1&&f.gt(h)&&f.isInt()&&n.gt(h)&&n.isInt()?f=f.mod(n):(i=n,n=null):v&&(r=mathceil(v/LOG_BASE+2)),o=new t(h);;){if(u%2){if(o=o.times(f),!o.c)break;r?o.c.length>r&&(o.c.length=r):n&&(o=o.mod(n))}if(u=mathfloor(u/2),!u)break;f=f.times(f),r?f.c&&f.c.length>r&&(f.c.length=r):n&&(f=f.mod(n))}return n?o:(0>e&&(o=h.div(o)),i?o.mod(i):r?s(o,v,A):o)},g.toPrecision=function(e,t){return r(this,null!=e&&b(e,1,MAX,24,"precision")?0|e:null,t,24)},g.toString=function(e){var t,r=this,o=r.s,i=r.e;return null===i?o?(t="Infinity",0>o&&(t="-"+t)):t="NaN":(t=coeffToString(r.c),t=null!=e&&b(e,2,64,25,"base")?n(toFixedPoint(t,i),0|e,10,o):S>=i||i>=E?toExponential(t,i):toFixedPoint(t,i),0>o&&r.c[0]&&(t="-"+t)),t},g.truncated=g.trunc=function(){return s(new t(this),this.e+1,1)},g.valueOf=g.toJSON=function(){var e,t=this,n=t.e;return null===n?t.toString():(e=coeffToString(t.c),e=S>=n||n>=E?toExponential(e,n):toFixedPoint(e,n),t.s<0?"-"+e:e)},g.isBigNumber=!0,null!=e&&t.config(e),t}function bitFloor(e){var t=0|e;return e>0||e===t?t:t-1}function coeffToString(e){for(var t,n,r=1,o=e.length,i=e[0]+"";o>r;){for(t=e[r++]+"",n=LOG_BASE-t.length;n--;t="0"+t);i+=t}for(o=i.length;48===i.charCodeAt(--o););return i.slice(0,o+1||1)}function compare(e,t){var n,r,o=e.c,i=t.c,u=e.s,f=t.s,s=e.e,c=t.e;if(!u||!f)return null;if(n=o&&!o[0],r=i&&!i[0],n||r)return n?r?0:-f:u;if(u!=f)return u;if(n=0>u,r=s==c,!o||!i)return r?0:!o^n?1:-1;if(!r)return s>c^n?1:-1;for(f=(s=o.length)<(c=i.length)?s:c,u=0;f>u;u++)if(o[u]!=i[u])return o[u]>i[u]^n?1:-1;return s==c?0:s>c^n?1:-1}function intValidatorNoErrors(e,t,n){return(e=truncate(e))>=t&&n>=e}function isArray(e){return"[object Array]"==Object.prototype.toString.call(e)}function toBaseOut(e,t,n){for(var r,o,i=[0],u=0,f=e.length;f>u;){for(o=i.length;o--;i[o]*=t);for(i[r=0]+=ALPHABET.indexOf(e.charAt(u++));r<i.length;r++)i[r]>n-1&&(null==i[r+1]&&(i[r+1]=0),i[r+1]+=i[r]/n|0,i[r]%=n)}return i.reverse()}function toExponential(e,t){return(e.length>1?e.charAt(0)+"."+e.slice(1):e)+(0>t?"e":"e+")+t}function toFixedPoint(e,t){var n,r;if(0>t){for(r="0.";++t;r+="0");e=r+e}else if(n=e.length,++t>n){for(r="0",t-=n;--t;r+="0");e+=r}else n>t&&(e=e.slice(0,t)+"."+e.slice(t));return e}function truncate(e){return e=parseFloat(e),0>e?mathceil(e):mathfloor(e)}function json_parse(e){"use strict";var t={strict:!1,storeAsString:!1};void 0!==e&&null!==e&&(e.strict===!0&&(t.strict=!0),e.storeAsString===!0&&(t.storeAsString=!0));var n,r,o,i,u={'"':'"',"\\":"\\","/":"/",b:"\b",f:"\f",n:"\n",r:"\r",t:" "},f=function(e){throw{name:"SyntaxError",message:e,at:n,text:o}},s=function(e){return e&&e!==r&&f("Expected '"+e+"' instead of '"+r+"'"),r=o.charAt(n),n+=1,r},c=function(){var e,n="";for("-"===r&&(n="-",s("-"));r>="0"&&"9">=r;)n+=r,s();if("."===r)for(n+=".";s()&&r>="0"&&"9">=r;)n+=r;if("e"===r||"E"===r)for(n+=r,s(),("-"===r||"+"===r)&&(n+=r,s());r>="0"&&"9">=r;)n+=r,s();return e=+n,isFinite(e)?(null==BigNumber&&(BigNumber=require("bignumber.js")),n.length>15?t.storeAsString===!0?n:new BigNumber(n):e):void f("Bad number")},l=function(){var e,t,n,o="";if('"'===r)for(;s();){if('"'===r)return s(),o;if("\\"===r)if(s(),"u"===r){for(n=0,t=0;4>t&&(e=parseInt(s(),16),isFinite(e));t+=1)n=16*n+e;o+=String.fromCharCode(n)}else{if("string"!=typeof u[r])break;o+=u[r]}else o+=r}f("Bad string")},a=function(){for(;r&&" ">=r;)s()},g=function(){switch(r){case"t":return s("t"),s("r"),s("u"),s("e"),!0;case"f":return s("f"),s("a"),s("l"),s("s"),s("e"),!1;case"n":return s("n"),s("u"),s("l"),s("l"),null}f("Unexpected '"+r+"'")},h=function(){var e=[];if("["===r){if(s("["),a(),"]"===r)return s("]"),e;for(;r;){if(e.push(i()),a(),"]"===r)return s("]"),e;s(","),a()}}f("Bad array")},p=function(){var e,n={};if("{"===r){if(s("{"),a(),"}"===r)return s("}"),n;for(;r;){if(e=l(),a(),s(":"),t.strict===!0&&Object.hasOwnProperty.call(n,e)&&f('Duplicate key "'+e+'"'),n[e]=i(),a(),"}"===r)return s("}"),n;s(","),a()}}f("Bad object")};return i=function(){switch(a(),r){case"{":return p();case"[":return h();case'"':return l();case"-":return c();default:return r>="0"&&"9">=r?c():g()}},function(e,t){var u;return o=e+"",n=0,r=" ",u=i(),a(),r&&f("Syntax error"),"function"==typeof t?function s(e,n){var r,o=e[n];return o&&"object"==typeof o&&Object.keys(o).forEach(function(e){r=s(o,e),void 0!==r?o[e]=r:delete o[e]}),t.call(e,n,o)}({"":u},""):u}}function f(e){return 10>e?"0"+e:e}function quote(e){return escapable.lastIndex=0,escapable.test(e)?'"'+e.replace(escapable,function(e){var t=meta[e];return"string"==typeof t?t:"\\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+e+'"'}function str(e,t){var n,r,o,i,u,f=gap,s=t[e],c=null!=s&&(s instanceof BigNumber||s.isBigNumber);switch(s&&"object"==typeof s&&"function"==typeof s.toJSON&&(s=s.toJSON(e)),"function"==typeof rep&&(s=rep.call(t,e,s)),typeof s){case"string":return c?s:quote(s);case"number":return isFinite(s)?String(s):"null";case"boolean":case"null":return String(s);case"object":if(!s)return"null";if(gap+=indent,u=[],"[object Array]"===Object.prototype.toString.apply(s)){for(i=s.length,n=0;i>n;n+=1)u[n]=str(n,s)||"null";return o=0===u.length?"[]":gap?"[\n"+gap+u.join(",\n"+gap)+"\n"+f+"]":"["+u.join(",")+"]",gap=f,o}if(rep&&"object"==typeof rep)for(i=rep.length,n=0;i>n;n+=1)"string"==typeof rep[n]&&(r=rep[n],o=str(r,s),o&&u.push(quote(r)+(gap?": ":":")+o));else Object.keys(s).forEach(function(e){var t=str(e,s);t&&u.push(quote(e)+(gap?": ":":")+t)});return o=0===u.length?"{}":gap?"{\n"+gap+u.join(",\n"+gap)+"\n"+f+"}":"{"+u.join(",")+"}",gap=f,o}}var BigNumber,isNumeric=/^-?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,mathceil=Math.ceil,mathfloor=Math.floor,notBool=" not a boolean or binary digit",roundingMode="rounding mode",tooManyDigits="number type has more than 15 significant digits",ALPHABET="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_",BASE=1e14,LOG_BASE=14,MAX_SAFE_INTEGER=9007199254740991,POWS_TEN=[1,10,100,1e3,1e4,1e5,1e6,1e7,1e8,1e9,1e10,1e11,1e12,1e13],SQRT_BASE=1e7,MAX=1e9;BigNumber=constructorFactory(),BigNumber["default"]=BigNumber.BigNumber=BigNumber;var jso={},cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b"," ":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;jso.stringify=function(e,t,n){var r;if(gap="",indent="","number"==typeof n)for(r=0;n>r;r+=1)indent+=" ";else"string"==typeof n&&(indent=n);if(rep=t,t&&"function"!=typeof t&&("object"!=typeof t||"number"!=typeof t.length))throw new Error("JSON.stringify");return str("",{"":e})},jso.get=function(e){return{parse:json_parse(e),stringify:jso.stringify}};var JSON=jso.get();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment