diff --git a/break_eternity.cjs.js b/break_eternity.cjs.js index a49f322..d158161 100644 --- a/break_eternity.cjs.js +++ b/break_eternity.cjs.js @@ -285,42 +285,53 @@ var f_gamma = function f_gamma(n) { var np = n; l = l + 1 / (12 * np); np = np * n2; - l = l + 1 / (360 * np); + l = l - 1 / (360 * np); np = np * n2; l = l + 1 / (1260 * np); np = np * n2; - l = l + 1 / (1680 * np); + l = l - 1 / (1680 * np); np = np * n2; l = l + 1 / (1188 * np); np = np * n2; - l = l + 691 / (360360 * np); + l = l - 691 / (360360 * np); np = np * n2; l = l + 7 / (1092 * np); np = np * n2; - l = l + 3617 / (122400 * np); + l = l - 3617 / (122400 * np); return Math.exp(l) / scal1; }; var _EXPN1 = 0.36787944117144232159553; // exp(-1) var OMEGA = 0.56714329040978387299997; // W(1, 0) //from https://math.stackexchange.com/a/465183 // The evaluation can become inaccurate very close to the branch point +// Evaluates W(x, 0) if principal is true, W(x, -1) if principal is false var f_lambertw = function f_lambertw(z) { var tol = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1e-10; + var principal = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var w; var wn; if (!Number.isFinite(z)) { return z; } - if (z === 0) { - return z; - } - if (z === 1) { - return OMEGA; - } - if (z < 10) { - w = 0; + if (principal) { + if (z === 0) { + return z; + } + if (z === 1) { + return OMEGA; + } + if (z < 10) { + w = 0; + } else { + w = Math.log(z) - Math.log(Math.log(z)); + } } else { - w = Math.log(z) - Math.log(Math.log(z)); + if (z === 0) return -Infinity; + if (z <= -0.1) { + w = -2; + } else { + w = Math.log(-z) - Math.log(-Math.log(-z)); + } } for (var i = 0; i < 100; ++i) { wn = (z * Math.exp(-w) + w * w) / (w + 1); @@ -337,22 +348,32 @@ var f_lambertw = function f_lambertw(z) { // The evaluation can become inaccurate very close to the branch point // at ``-1/e``. In some corner cases, `lambertw` might currently // fail to converge, or can end up on the wrong branch. +// Evaluates W(x, 0) if principal is true, W(x, -1) if principal is false function d_lambertw(z) { var tol = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1e-10; + var principal = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var w; var ew, wewz, wn; if (!Number.isFinite(z.mag)) { - return z; - } - if (z.eq(Decimal.dZero)) { - return z; + return new Decimal(z); } - if (z.eq(Decimal.dOne)) { - //Split out this case because the asymptotic series blows up - return Decimal.fromNumber(OMEGA); + if (principal) { + if (z.eq(Decimal.dZero)) { + return FC_NN(0, 0, 0); + } + if (z.eq(Decimal.dOne)) { + //Split out this case because the asymptotic series blows up + return Decimal.fromNumber(OMEGA); + } + //Get an initial guess for Halley's method + w = Decimal.ln(z); + } else { + if (z.eq(Decimal.dZero)) { + return FC_NN(-1, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY); + } + //Get an initial guess for Halley's method + w = Decimal.ln(z.neg()); } - //Get an initial guess for Halley's method - w = Decimal.ln(z); //Halley's method; see 5.9 in [1] for (var i = 0; i < 100; ++i) { ew = w.neg().exp(); @@ -491,7 +512,7 @@ var Decimal = /*#__PURE__*/function () { Any 0 is totally zero (0, 0, 0) and any NaN is totally NaN (NaN, NaN, NaN). Anything layer 0 has mag 0 OR mag > 1/9e15 and < 9e15. Anything layer 1 or higher has abs(mag) >= 15.954 and < 9e15. - Any positive infinity is (1, Infinity, Infinity) and any negative infinity is (-1, -Infinity, -Infinity). + Any positive infinity is (1, Infinity, Infinity) and any negative infinity is (-1, Infinity, Infinity). We will assume in calculations that all Decimals are either erroneous or satisfy these criteria. (Otherwise: Garbage in, garbage out.) */ //Any 0 is totally 0 @@ -508,13 +529,8 @@ var Decimal = /*#__PURE__*/function () { } //Handle infinities if (this.mag === Number.POSITIVE_INFINITY || this.layer === Number.POSITIVE_INFINITY || this.mag === Number.NEGATIVE_INFINITY || this.layer === Number.NEGATIVE_INFINITY) { - if (this.sign == 1) { - this.mag = Number.POSITIVE_INFINITY; - this.layer = Number.POSITIVE_INFINITY; - } else if (this.sign == -1) { - this.mag = Number.NEGATIVE_INFINITY; - this.layer = Number.NEGATIVE_INFINITY; - } + this.mag = Number.POSITIVE_INFINITY; + this.layer = Number.POSITIVE_INFINITY; return this; } //Handle shifting from layer 0 to negative layers. @@ -730,6 +746,11 @@ var Decimal = /*#__PURE__*/function () { var ptparts = value.split("pt"); if (ptparts.length === 2) { base = 10; + var negative = false; + if (ptparts[0][0] == "-") { + negative = true; + ptparts[0] = ptparts[0].slice(1); + } height = parseFloat(ptparts[0]); ptparts[1] = ptparts[1].replace("(", ""); ptparts[1] = ptparts[1].replace(")", ""); @@ -745,6 +766,7 @@ var Decimal = /*#__PURE__*/function () { if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } + if (negative) this.sign *= -1; return this; } } @@ -752,6 +774,11 @@ var Decimal = /*#__PURE__*/function () { ptparts = value.split("p"); if (ptparts.length === 2) { base = 10; + var _negative = false; + if (ptparts[0][0] == "-") { + _negative = true; + ptparts[0] = ptparts[0].slice(1); + } height = parseFloat(ptparts[0]); ptparts[1] = ptparts[1].replace("(", ""); ptparts[1] = ptparts[1].replace(")", ""); @@ -767,6 +794,7 @@ var Decimal = /*#__PURE__*/function () { if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } + if (_negative) this.sign *= -1; return this; } } @@ -774,6 +802,11 @@ var Decimal = /*#__PURE__*/function () { ptparts = value.split("f"); if (ptparts.length === 2) { base = 10; + var _negative2 = false; + if (ptparts[0][0] == "-") { + _negative2 = true; + ptparts[0] = ptparts[0].slice(1); + } ptparts[0] = ptparts[0].replace("(", ""); ptparts[0] = ptparts[0].replace(")", ""); var _payload4 = parseFloat(ptparts[0]); @@ -791,6 +824,7 @@ var Decimal = /*#__PURE__*/function () { if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } + if (_negative2) this.sign *= -1; return this; } } @@ -938,7 +972,7 @@ var Decimal = /*#__PURE__*/function () { if (this.mag === Number.POSITIVE_INFINITY && this.layer === Number.POSITIVE_INFINITY && this.sign === 1) { return Number.POSITIVE_INFINITY; } - if (this.mag === Number.NEGATIVE_INFINITY && this.layer === Number.NEGATIVE_INFINITY && this.sign === -1) { + if (this.mag === Number.POSITIVE_INFINITY && this.layer === Number.POSITIVE_INFINITY && this.sign === -1) { return Number.NEGATIVE_INFINITY; } if (!Number.isFinite(this.layer)) { @@ -988,7 +1022,7 @@ var Decimal = /*#__PURE__*/function () { if (isNaN(this.layer) || isNaN(this.sign) || isNaN(this.mag)) { return "NaN"; } - if (this.mag === Number.POSITIVE_INFINITY || this.layer === Number.POSITIVE_INFINITY || this.mag === Number.NEGATIVE_INFINITY || this.layer === Number.NEGATIVE_INFINITY) { + if (this.mag === Number.POSITIVE_INFINITY || this.layer === Number.POSITIVE_INFINITY) { return this.sign === 1 ? "Infinity" : "-Infinity"; } if (this.layer === 0) { @@ -1113,12 +1147,12 @@ var Decimal = /*#__PURE__*/function () { key: "round", value: function round() { if (this.mag < 0) { - return Decimal.dZero; + return FC_NN(0, 0, 0); } if (this.layer === 0) { return FC(this.sign, 0, Math.round(this.mag)); } - return this; + return new Decimal(this); } /** * "Rounds" the Decimal it's called on to the nearest integer that's less than or equal to it. @@ -1127,13 +1161,13 @@ var Decimal = /*#__PURE__*/function () { key: "floor", value: function floor() { if (this.mag < 0) { - if (this.sign === -1) return Decimal.dNegOne;else return Decimal.dZero; + if (this.sign === -1) return FC_NN(-1, 0, 1);else return FC_NN(0, 0, 0); } if (this.sign === -1) return this.neg().ceil().neg(); if (this.layer === 0) { return FC(this.sign, 0, Math.floor(this.mag)); } - return this; + return new Decimal(this); } /** * "Rounds" the Decimal it's called on to the nearest integer that's greater than or equal to it. @@ -1142,14 +1176,14 @@ var Decimal = /*#__PURE__*/function () { key: "ceil", value: function ceil() { if (this.mag < 0) { - if (this.sign === 1) return Decimal.dOne; //The ceiling function called on something tiny like 10^10^-100 should return 1, since 10^10^-100 is still greater than 0 - else return Decimal.dZero; + if (this.sign === 1) return FC_NN(1, 0, 1); //The ceiling function called on something tiny like 10^10^-100 should return 1, since 10^10^-100 is still greater than 0 + else return FC_NN(0, 0, 0); } if (this.sign === -1) return this.neg().floor().neg(); if (this.layer === 0) { return FC(this.sign, 0, Math.ceil(this.mag)); } - return this; + return new Decimal(this); } /** * Extracts the integer part of the Decimal and returns it. Behaves like floor on positive numbers, but behaves like ceiling on negative numbers. @@ -1158,12 +1192,12 @@ var Decimal = /*#__PURE__*/function () { key: "trunc", value: function trunc() { if (this.mag < 0) { - return Decimal.dZero; + return FC_NN(0, 0, 0); } if (this.layer === 0) { return FC(this.sign, 0, Math.trunc(this.mag)); } - return this; + return new Decimal(this); } /** * Addition: returns the sum of 'this' and 'value'. @@ -1172,19 +1206,23 @@ var Decimal = /*#__PURE__*/function () { key: "add", value: function add(value) { var decimal = D(value); + //Infinity + -Infinity = NaN + if (this.eq(Decimal.dInf) && decimal.eq(Decimal.dNegInf) || this.eq(Decimal.dNegInf) && decimal.eq(Decimal.dInf)) { + return FC_NN(Number.NaN, Number.NaN, Number.NaN); + } //inf/nan check if (!Number.isFinite(this.layer)) { - return this; + return new Decimal(this); } if (!Number.isFinite(decimal.layer)) { - return decimal; + return new Decimal(decimal); } //Special case - if one of the numbers is 0, return the other number. if (this.sign === 0) { - return decimal; + return new Decimal(decimal); } if (decimal.sign === 0) { - return this; + return new Decimal(this); } //Special case - Adding a number to its negation produces 0, no matter how large. if (this.sign === -decimal.sign && this.layer === decimal.layer && this.mag === decimal.mag) { @@ -1197,11 +1235,11 @@ var Decimal = /*#__PURE__*/function () { return this.maxabs(decimal); } if (Decimal.cmpabs(this, decimal) > 0) { - a = this; - b = decimal; + a = new Decimal(this); + b = new Decimal(decimal); } else { - a = decimal; - b = this; + a = new Decimal(decimal); + b = new Decimal(this); } if (a.layer === 0 && b.layer === 0) { return Decimal.fromNumber(a.sign * a.mag + b.sign * b.mag); @@ -1277,12 +1315,20 @@ var Decimal = /*#__PURE__*/function () { key: "mul", value: function mul(value) { var decimal = D(value); + // Infinity * -Infinity = -Infinity + if (this.eq(Decimal.dInf) && decimal.eq(Decimal.dNegInf) || this.eq(Decimal.dNegInf) && decimal.eq(Decimal.dInf)) { + return FC_NN(-1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); + } + //Infinity * 0 = NaN + if (this.mag == Number.POSITIVE_INFINITY && decimal.eq(Decimal.dZero) || this.eq(Decimal.dZero) && this.mag == Number.POSITIVE_INFINITY) { + return FC_NN(Number.NaN, Number.NaN, Number.NaN); + } //inf/nan check if (!Number.isFinite(this.layer)) { - return this; + return new Decimal(this); } if (!Number.isFinite(decimal.layer)) { - return decimal; + return new Decimal(decimal); } //Special case - if one of the numbers is 0, return 0. if (this.sign === 0 || decimal.sign === 0) { @@ -1296,11 +1342,11 @@ var Decimal = /*#__PURE__*/function () { var b; //Which number is bigger in terms of its multiplicative distance from 1? if (this.layer > decimal.layer || this.layer == decimal.layer && Math.abs(this.mag) > Math.abs(decimal.mag)) { - a = this; - b = decimal; + a = new Decimal(this); + b = new Decimal(decimal); } else { - a = decimal; - b = this; + a = new Decimal(decimal); + b = new Decimal(this); } if (a.layer === 0 && b.layer === 0) { return Decimal.fromNumber(a.sign * b.sign * a.mag * b.mag); @@ -1381,7 +1427,9 @@ var Decimal = /*#__PURE__*/function () { key: "recip", value: function recip() { if (this.mag === 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); + } else if (this.mag === Number.POSITIVE_INFINITY) { + return FC_NN(0, 0, 0); } else if (this.layer === 0) { return FC(this.sign, 0, 1 / this.mag); } else { @@ -1413,7 +1461,7 @@ var Decimal = /*#__PURE__*/function () { key: "mod", value: function mod(value) { var decimal = D(value).abs(); - if (decimal.eq(Decimal.dZero)) return Decimal.dZero; + if (decimal.eq(Decimal.dZero)) return FC_NN(0, 0, 0); var num_this = this.toNumber(); var num_decimal = decimal.toNumber(); //Special case: To avoid precision issues, if both numbers are valid JS numbers, just call % on those @@ -1422,11 +1470,11 @@ var Decimal = /*#__PURE__*/function () { } if (this.sub(decimal).eq(this)) { //decimal is too small to register to this - return Decimal.dZero; + return FC_NN(0, 0, 0); } if (decimal.sub(this).eq(decimal)) { //this is too small to register to decimal - return this; + return new Decimal(this); } if (this.sign == -1) return this.abs().mod(decimal).neg(); return this.sub(this.div(decimal).floor().mul(decimal)); @@ -1592,7 +1640,7 @@ var Decimal = /*#__PURE__*/function () { key: "max", value: function max(value) { var decimal = D(value); - return this.lt(decimal) ? decimal : this; + return this.lt(decimal) ? new Decimal(decimal) : new Decimal(this); } /** * Returns whichever of 'this' and 'value' is lower. @@ -1601,7 +1649,7 @@ var Decimal = /*#__PURE__*/function () { key: "min", value: function min(value) { var decimal = D(value); - return this.gt(decimal) ? decimal : this; + return this.gt(decimal) ? new Decimal(decimal) : new Decimal(this); } /** * Returns whichever of 'this' and 'value' has a larger absolute value. @@ -1610,7 +1658,7 @@ var Decimal = /*#__PURE__*/function () { key: "maxabs", value: function maxabs(value) { var decimal = D(value); - return this.cmpabs(decimal) < 0 ? decimal : this; + return this.cmpabs(decimal) < 0 ? new Decimal(decimal) : new Decimal(this); } /** * Returns whichever of 'this' and 'value' has a smaller absolute value. @@ -1619,7 +1667,7 @@ var Decimal = /*#__PURE__*/function () { key: "minabs", value: function minabs(value) { var decimal = D(value); - return this.cmpabs(decimal) > 0 ? decimal : this; + return this.cmpabs(decimal) > 0 ? new Decimal(decimal) : new Decimal(this); } /** * A combination of minimum and maximum: the value returned by clamp is normally 'this', but it won't go below 'min' and it won't go above 'max'. @@ -1794,7 +1842,7 @@ var Decimal = /*#__PURE__*/function () { key: "pLog10", value: function pLog10() { if (this.lt(Decimal.dZero)) { - return Decimal.dZero; + return FC_NN(0, 0, 0); } return this.log10(); } @@ -1805,7 +1853,7 @@ var Decimal = /*#__PURE__*/function () { key: "absLog10", value: function absLog10() { if (this.sign === 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } else if (this.layer > 0) { return FC(Math.sign(this.mag), this.layer - 1, Math.abs(this.mag)); } else { @@ -1820,7 +1868,7 @@ var Decimal = /*#__PURE__*/function () { key: "log10", value: function log10() { if (this.sign <= 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } else if (this.layer > 0) { return FC(Math.sign(this.mag), this.layer - 1, Math.abs(this.mag)); } else { @@ -1835,13 +1883,13 @@ var Decimal = /*#__PURE__*/function () { value: function log(base) { base = D(base); if (this.sign <= 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } if (base.sign <= 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } if (base.sign === 1 && base.layer === 0 && base.mag === 1) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } else if (this.layer === 0 && base.layer === 0) { return FC(this.sign, 0, Math.log(this.mag) / Math.log(base.mag)); } @@ -1854,7 +1902,7 @@ var Decimal = /*#__PURE__*/function () { key: "log2", value: function log2() { if (this.sign <= 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } else if (this.layer === 0) { return FC(this.sign, 0, Math.log2(this.mag)); } else if (this.layer === 1) { @@ -1872,7 +1920,7 @@ var Decimal = /*#__PURE__*/function () { key: "ln", value: function ln() { if (this.sign <= 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } else if (this.layer === 0) { return FC(this.sign, 0, Math.log(this.mag)); } else if (this.layer === 1) { @@ -1898,8 +1946,8 @@ var Decimal = /*#__PURE__*/function () { key: "pow", value: function pow(value) { var decimal = D(value); - var a = this; - var b = decimal; + var a = new Decimal(this); + var b = new Decimal(decimal); //special case: if a is 0, then return 0 (UNLESS b is 0, then return 1) if (a.sign === 0) { return b.eq(0) ? FC_NN(1, 0, 1) : a; @@ -1923,7 +1971,7 @@ var Decimal = /*#__PURE__*/function () { } else if (Math.abs(b.toNumber() % 2) % 2 === 0) { return result; } - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } return result; } @@ -1940,10 +1988,16 @@ var Decimal = /*#__PURE__*/function () { 3) positive sign, negative mag (e-15, ee-15): layer 0 case would have been handled in the Math.pow check, so just return 1 4) negative sign, negative mag (-e-15, -ee-15): layer 0 case would have been handled in the Math.pow check, so just return 1 */ + if (this.eq(Decimal.dInf)) { + return FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); + } + if (this.eq(Decimal.dNegInf)) { + return FC_NN(0, 0, 0); + } if (!Number.isFinite(this.layer) || !Number.isFinite(this.mag)) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } - var a = this; + var a = new Decimal(this); //handle layer 0 case - if no precision is lost just use Math.pow, else promote one layer if (a.layer === 0) { var newmag = Math.pow(10, a.sign * a.mag); @@ -1951,7 +2005,7 @@ var Decimal = /*#__PURE__*/function () { return FC(1, 0, newmag); } else { if (a.sign === 0) { - return Decimal.dOne; + return FC_NN(1, 0, 1); } else { a = FC_NN(a.sign, a.layer + 1, Math.log10(a.mag)); } @@ -1965,7 +2019,7 @@ var Decimal = /*#__PURE__*/function () { return FC(-a.sign, a.layer + 1, -a.mag); } //both the negative mag cases are identical: one +/- rounding error - return Decimal.dOne; + return FC_NN(1, 0, 1); } /** * Exponentiation: Returns the result of 'value' ^ 'this' (often written as 'value' ** 'this' in programming languages). @@ -2068,7 +2122,7 @@ var Decimal = /*#__PURE__*/function () { key: "exp", value: function exp() { if (this.mag < 0) { - return Decimal.dOne; + return FC_NN(1, 0, 1); } if (this.layer === 0 && this.mag <= 709.7) { return Decimal.fromNumber(Math.exp(this.sign * this.mag)); @@ -2148,7 +2202,7 @@ var Decimal = /*#__PURE__*/function () { } //1^^x == 1 if (this.eq(Decimal.dOne)) { - return Decimal.dOne; + return FC_NN(1, 0, 1); } //-1^^x == -1 if (this.eq(-1)) { @@ -2158,21 +2212,25 @@ var Decimal = /*#__PURE__*/function () { var this_num = this.toNumber(); //within the convergence range? if (this_num <= 1.44466786100976613366 && this_num >= 0.06598803584531253708) { + var negln = Decimal.ln(this).neg(); + //For bases above 1, b^x = x has two solutions. The lower solution is a stable equilibrium, the upper solution is an unstable equilibrium. + var lower = negln.lambertw().div(negln); + // However, if the base is below 1, there's only the stable equilibrium solution. + if (this_num < 1) return lower; + var upper = negln.lambertw(false).div(negln); //hotfix for the very edge of the number range not being handled properly if (this_num > 1.444667861009099) { - return Decimal.fromNumber(Math.E); + lower = upper = Decimal.fromNumber(Math.E); } - //Formula for infinite height power tower. - var negln = Decimal.ln(this).neg(); - return negln.lambertw().div(negln); + payload = D(payload); + if (payload.eq(upper)) return upper;else if (payload.lt(upper)) return lower;else return FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); } else if (this_num > 1.44466786100976613366) { //explodes to infinity - // TODO: replace this with Decimal.dInf - return Decimal.fromNumber(Number.POSITIVE_INFINITY); + return FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); } else { //0.06598803584531253708 > this_num >= 0: never converges //this_num < 0: quickly becomes a complex number - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } } //0^^x oscillates if we define 0^0 == 1 (which in javascript land we do), since then 0^^1 is 0, 0^^2 is 1, 0^^3 is 0, etc. payload is ignored @@ -2187,14 +2245,15 @@ var Decimal = /*#__PURE__*/function () { if (height < 0) { return Decimal.iteratedlog(payload, this, -height, linear); } - payload = D(payload); + payload = new Decimal(payload); var oldheight = height; height = Math.trunc(height); var fracheight = oldheight - height; - if (this.gt(Decimal.dZero) && this.lte(1.44466786100976613366) && (oldheight > 10000 || !linear)) { - //similar to 0^^n, flip-flops between two values, converging slowly (or if it's below 0.06598803584531253708, never. so once again, the fractional part at the end will be a linear approximation (TODO: again pending knowledge of how to approximate better, although tbh I think it should in reality just be NaN) - height = Math.min(10000, height); - for (var i = 0; i < height; ++i) { + if (this.gt(Decimal.dZero) && (this.lt(1) || this.lte(1.44466786100976613366) && payload.lte(Decimal.ln(this).neg().lambertw(false).div(Decimal.ln(this).neg()))) && (oldheight > 10000 || !linear)) { + //similar to 0^^n, flip-flops between two values, converging slowly (or if it's below 0.06598803584531253708, never). So once again, the fractional part at the beginning will be a linear approximation (TODO: again pending knowledge of how to approximate better, although tbh I think it should in reality just be NaN) + var limitheight = Math.min(10000, height); + if (payload.eq(Decimal.dOne)) payload = this.pow(fracheight);else if (this.lt(1)) payload = payload.pow(1 - fracheight).mul(this.pow(payload).pow(fracheight));else payload = payload.layeradd(fracheight, this); + for (var i = 0; i < limitheight; ++i) { var old_payload = payload; payload = this.pow(payload); //stop early if we converge @@ -2202,13 +2261,8 @@ var Decimal = /*#__PURE__*/function () { return payload; } } - if (fracheight != 0 || oldheight > 10000) { - var next_payload = this.pow(payload); - if (oldheight <= 10000 || Math.ceil(oldheight) % 2 == 0) { - return payload.mul(1 - fracheight).add(next_payload.mul(fracheight)); - } else { - return payload.mul(fracheight).add(next_payload.mul(1 - fracheight)); - } + if (oldheight > 10000 && Math.ceil(oldheight) % 2 == 1) { + return this.pow(payload); } return payload; } @@ -2230,6 +2284,8 @@ var Decimal = /*#__PURE__*/function () { } else { if (this.eq(10)) { payload = payload.layeradd10(fracheight, linear); + } else if (this.lt(1)) { + payload = payload.pow(1 - fracheight).mul(this.pow(payload).pow(fracheight)); } else { payload = payload.layeradd(fracheight, this, linear); } @@ -2313,6 +2369,7 @@ var Decimal = /*#__PURE__*/function () { if (base.eq(10)) { result = result.layeradd10(-fraction, linear); } else { + //I have no clue what a fractional times on a base below 1 should even mean, so I'm not going to bother - just let it be NaN (TODO: come up with what the answer actually should be) result = result.layeradd(-fraction, base, linear); } } @@ -2371,28 +2428,34 @@ var Decimal = /*#__PURE__*/function () { //special cases: //slog base 0 or lower is NaN if (base.lte(Decimal.dZero)) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //slog base 1 is NaN if (base.eq(Decimal.dOne)) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //need to handle these small, wobbling bases specially if (base.lt(Decimal.dOne)) { if (this.eq(Decimal.dOne)) { - return Decimal.dZero; + return FC_NN(0, 0, 0); } if (this.eq(Decimal.dZero)) { - return Decimal.dNegOne; + return FC_NN(-1, 0, 1); } //0 < this < 1: ambiguous (happens multiple times) //this < 0: impossible (as far as I can tell) //this > 1: partially complex (http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html base 0.25 for proof) - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //slog_n(0) is -1 if (this.mag < 0 || this.eq(Decimal.dZero)) { - return Decimal.dNegOne; + return FC_NN(-1, 0, 1); + } + if (base.lt(1.44466786100976613366)) { + var negln = Decimal.ln(base).neg(); + var infTower = negln.lambertw().div(negln); + if (this.eq(infTower)) return FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); + if (this.gt(infTower)) return FC_NN(Number.NaN, Number.NaN, Number.NaN); } var result = 0; var copy = Decimal.fromDecimal(this); @@ -2503,41 +2566,87 @@ var Decimal = /*#__PURE__*/function () { key: "layeradd", value: function layeradd(diff, base) { var linear = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; - var slogthis = this.slog(base).toNumber(); + var baseD = D(base); + if (baseD.gt(1) && baseD.lte(1.44466786100976613366)) { + var excessSlog = Decimal.excess_slog(this, base, linear); + var _slogthis = excessSlog[0].toNumber(); + var range = excessSlog[1]; + var _slogdest = _slogthis + diff; + var negln = Decimal.ln(base).neg(); + var lower = negln.lambertw().div(negln); + var upper = negln.lambertw(false).div(negln); + var slogzero = Decimal.dOne; + if (range == 1) slogzero = lower.mul(upper).sqrt();else if (range == 2) slogzero = upper.mul(2); + var slogone = baseD.pow(slogzero); + var wholeheight = Math.floor(_slogdest); + var fracheight = _slogdest - wholeheight; + var towertop = slogzero.pow(1 - fracheight).mul(slogone.pow(fracheight)); + return Decimal.tetrate(baseD, wholeheight, towertop, linear); //wholediff is a whole number so this is safe even if it ends up calling iteratedlog + } + + var slogthis = this.slog(base, 100, linear).toNumber(); var slogdest = slogthis + diff; if (slogdest >= 0) { return Decimal.tetrate(base, slogdest, Decimal.dOne, linear); } else if (!Number.isFinite(slogdest)) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } else if (slogdest >= -1) { return Decimal.log(Decimal.tetrate(base, slogdest + 1, Decimal.dOne, linear), base); } else { return Decimal.log(Decimal.log(Decimal.tetrate(base, slogdest + 2, Decimal.dOne, linear), base), base); } } + //Apparently having something be private but not static breaks everything + /** + * A strange version of slog for bases between 1 and e^1/e which can handle values above base^^Infinity. + * Returns a pair of a Decimal and a number, with the number always being 0, 1, or 2. The number indicates what range we're in: + * 0 means we're below the lower solution of b^x = x, and so the normal slog is used. + * 1 means we're between the two solutions of b^x = x, with the geometric mean of the two solutions arbitrarily chosen to be the value with a slog of 0. + * 2 means we're above the upper solution of b^x = x, with (upper solution * 2) arbitrarily chosen to be the value with a slog of 0. + * + * The values returned by this function don't really have much mathematical meaning, but the difference between two values does. + * Therefore, this function is kept private, but it's used for layeradd on these small bases. + */ + }, { + key: "lambertw", + value: /** * The Lambert W function, also called the omega function or product logarithm, is the solution W(x) === x*e^x. * https://en.wikipedia.org/wiki/Lambert_W_function + * + * This is a multi-valued function in the complex plane, but only two branches matter for real numbers: the "principal branch" W0, and the "non-principal branch" W_-1. + * W_0 works for any number >= -1/e, but W_-1 only works for nonpositive numbers >= -1/e. + * The "principal" parameter, which is true by default, decides which branch we're looking for: W_0 is used if principal is true, W_-1 is used if principal is false. */ //Some special values, for testing: https://en.wikipedia.org/wiki/Lambert_W_function#Special_values - }, { - key: "lambertw", - value: function lambertw() { + function lambertw() { + var principal = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; if (this.lt(-0.3678794411710499)) { - throw Error("lambertw is unimplemented for results less than -1, sorry!"); - } else if (this.mag < 0) { - return Decimal.fromNumber(f_lambertw(this.toNumber())); - } else if (this.layer === 0) { - return Decimal.fromNumber(f_lambertw(this.sign * this.mag)); - } else if (this.layer === 1) { - return d_lambertw(this); - } else if (this.layer === 2) { - return d_lambertw(this); - } - if (this.layer >= 3) { - return FC_NN(this.sign, this.layer - 1, this.mag); + return FC_NN(Number.NaN, Number.NaN, Number.NaN); //complex + } else if (principal) { + if (this.abs().lt("1e-300")) return new Decimal(this);else if (this.mag < 0) { + return Decimal.fromNumber(f_lambertw(this.toNumber())); + } else if (this.layer === 0) { + return Decimal.fromNumber(f_lambertw(this.sign * this.mag)); + } else if (this.lt("eee15")) { + return d_lambertw(this); + } else { + // Numbers this large would sometimes fail to converge using d_lambertw, and at this size this.ln() is close enough + return this.ln(); + } + } else { + if (this.sign === 1) { + return FC_NN(Number.NaN, Number.NaN, Number.NaN); //complex + } + + if (this.layer === 0) { + return Decimal.fromNumber(f_lambertw(this.sign * this.mag, 1e-10, false)); + } else if (this.layer == 1) { + return d_lambertw(this, 1e-10, false); + } else { + return this.neg().recip().lambertw().neg(); + } } - throw "Unhandled behavior in lambertw()"; } /** * The super square-root function - what number, tetrated to height 2, equals 'this'? https://en.wikipedia.org/wiki/Tetration#Super-root @@ -2563,10 +2672,10 @@ var Decimal = /*#__PURE__*/function () { return this; } if (this.eq(Decimal.dInf)) { - return Decimal.dInf; + return FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); } if (!this.isFinite()) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //Using linear approximation, x^^n = x^n if 0 < n < 1 if (degree > 0 && degree < 1) { @@ -2578,7 +2687,7 @@ var Decimal = /*#__PURE__*/function () { } //Super roots with -1 <= degree < 0 have either no solution or infinitely many solutions, and tetration with height <= -2 returns NaN, so super roots of degree <= -2 don't work if (degree <= 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //Infinite degree super-root is x^(1/x) between 1/e <= x <= e, undefined otherwise if (degree == Number.POSITIVE_INFINITY) { @@ -2586,20 +2695,20 @@ var Decimal = /*#__PURE__*/function () { if (this_num < Math.E && this_num > _EXPN1) { return this.pow(this.recip()); } else { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } } //Special case: any super-root of 1 is 1 if (this.eq(1)) { - return Decimal.dOne; + return FC_NN(1, 0, 1); } //TODO: base < 0 (It'll probably be NaN anyway) if (this.lt(0)) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //Treat all numbers of layer <= -2 as zero, because they effectively are if (this.lte("1ee-16")) { - if (degree % 2 == 1) return this;else return Decimal.dNaN; + if (degree % 2 == 1) return new Decimal(this);else return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //this > 1 if (this.gt(1)) { @@ -2791,7 +2900,7 @@ var Decimal = /*#__PURE__*/function () { if (_lower.eq(FC(1, 10, 1))) _guess = _upper.mul(2);else _guess = _lower.add(_upper).div(2); if (Decimal.pow(10, _guess).recip().tetrate(degree, 1, true).gt(this)) _upper = _guess;else _lower = _guess; if (_guess.eq(_previous)) _loopGoing = false;else _previous = _guess; - if (_upper.gt("1e18")) return Decimal.dNaN; + if (_upper.gt("1e18")) return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //using guess.neq(minimum) led to imprecision errors, so here's a fixed version of that if (!_guess.eq_tolerance(minimum, 1e-15)) { @@ -2801,7 +2910,7 @@ var Decimal = /*#__PURE__*/function () { //Check if the root is in the zero range. if (maximum.eq(FC(1, 10, 1))) { //There is no zero range, so the super root doesn't exist - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } _lower = FC(1, 10, 1); _upper = maximum; @@ -2812,7 +2921,7 @@ var Decimal = /*#__PURE__*/function () { if (_lower.eq(FC(1, 10, 1))) _guess = _upper.mul(2);else _guess = _lower.add(_upper).div(2); if (Decimal.pow(10, _guess).recip().tetrate(degree, 1, true).gt(this)) _upper = _guess;else _lower = _guess; if (_guess.eq(_previous)) _loopGoing = false;else _previous = _guess; - if (_upper.gt("1e18")) return Decimal.dNaN; + if (_upper.gt("1e18")) return FC_NN(Number.NaN, Number.NaN, Number.NaN); } return _guess.pow10().recip(); } @@ -2835,7 +2944,7 @@ var Decimal = /*#__PURE__*/function () { var height = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 2; var payload = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : FC_NN(1, 0, 1); var linear = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; - payload = D(payload); + payload = new Decimal(payload); var oldheight = height; height = Math.trunc(height); var fracheight = oldheight - height; @@ -2873,7 +2982,7 @@ var Decimal = /*#__PURE__*/function () { key: "sin", value: function sin() { if (this.mag < 0) { - return this; + return new Decimal(this); } if (this.layer === 0) { return Decimal.fromNumber(Math.sin(this.sign * this.mag)); @@ -2887,7 +2996,7 @@ var Decimal = /*#__PURE__*/function () { key: "cos", value: function cos() { if (this.mag < 0) { - return Decimal.dOne; + return FC_NN(1, 0, 1); } if (this.layer === 0) { return Decimal.fromNumber(Math.cos(this.sign * this.mag)); @@ -2901,7 +3010,7 @@ var Decimal = /*#__PURE__*/function () { key: "tan", value: function tan() { if (this.mag < 0) { - return this; + return new Decimal(this); } if (this.layer === 0) { return Decimal.fromNumber(Math.tan(this.sign * this.mag)); @@ -2915,7 +3024,7 @@ var Decimal = /*#__PURE__*/function () { key: "asin", value: function asin() { if (this.mag < 0) { - return this; + return new Decimal(this); } if (this.layer === 0) { return Decimal.fromNumber(Math.asin(this.sign * this.mag)); @@ -2943,7 +3052,7 @@ var Decimal = /*#__PURE__*/function () { key: "atan", value: function atan() { if (this.mag < 0) { - return this; + return new Decimal(this); } if (this.layer === 0) { return Decimal.fromNumber(Math.atan(this.sign * this.mag)); @@ -3008,7 +3117,7 @@ var Decimal = /*#__PURE__*/function () { key: "ascensionPenalty", value: function ascensionPenalty(ascensions) { if (ascensions === 0) { - return this; + return new Decimal(this); } return this.root(Decimal.pow(10, ascensions)); } @@ -3130,7 +3239,7 @@ var Decimal = /*#__PURE__*/function () { // This should never happen... but some users like Prestige Tree Rewritten // pass undefined values in as DecimalSources, so we should handle this // case to not break them. - return Decimal.dZero; + return FC_NN(0, 0, 0); } } /** @@ -3893,11 +4002,15 @@ var Decimal = /*#__PURE__*/function () { /** * The Lambert W function, also called the omega function or product logarithm, is the solution W(x) === x*e^x. * https://en.wikipedia.org/wiki/Lambert_W_function + * + * This is a multi-valued function in the complex plane, but only two branches matter for real numbers: the "principal branch" W0, and the "non-principal branch" W_-1. + * W_0 works for any number >= -1/e, but W_-1 only works for negative numbers >= -1/e. + * The "principal" parameter, which is true by default, decides which branch we're looking for: W_0 is used if principal is true, W_-1 is used if principal is false. */ }, { key: "lambertw", - value: function lambertw(value) { - return D(value).lambertw(); + value: function lambertw(value, principal) { + return D(value).lambertw(principal); } /** * The super square-root function - what number, tetrated to height 2, equals 'value'? https://en.wikipedia.org/wiki/Tetration#Super-root @@ -4206,6 +4319,109 @@ var Decimal = /*#__PURE__*/function () { return Math.pow(base, Math.log(lower) / Math.log(base) * (1 - frac) + Math.log(upper) / Math.log(base) * frac); } } + }, { + key: "excess_slog", + value: function excess_slog(value, base) { + var linear = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + value = D(value); + base = D(base); + var baseD = base; + base = base.toNumber(); + if (base == 1 || base <= 0) return [FC_NN(Number.NaN, Number.NaN, Number.NaN), 0]; + if (base > 1.44466786100976613366) return [value.slog(base, 100, linear), 0]; + var negln = Decimal.ln(base).neg(); + var lower = negln.lambertw().div(negln); + var upper = Decimal.dInf; + if (base > 1) upper = negln.lambertw(false).div(negln); + if (base > 1.444667861009099) { + lower = upper = Decimal.fromNumber(Math.E); + } + if (value.lt(lower)) return [value.slog(base, 100, linear), 0]; + if (value.eq(lower)) return [FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY), 0]; + if (value.eq(upper)) return [FC_NN(1, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY), 2]; + if (value.gt(upper)) { + var slogzero = upper.mul(2); + var slogone = baseD.pow(slogzero); + var estimate = 0; + if (value.gte(slogzero) && value.lt(slogone)) estimate = 0;else if (value.gte(slogone)) { + var payload = slogone; + estimate = 1; + while (payload.lt(value)) { + payload = baseD.pow(payload); + estimate = estimate + 1; + if (payload.layer > 3) { + var layersleft = Math.floor(value.layer - payload.layer + 1); + payload = baseD.iteratedexp(layersleft, payload, linear); + estimate = estimate + layersleft; + } + } + if (payload.gt(value)) { + payload = payload.log(base); + estimate = estimate - 1; + } + } else if (value.lt(slogzero)) { + var _payload5 = slogzero; + estimate = 0; + while (_payload5.gt(value)) { + _payload5 = _payload5.log(base); + estimate = estimate - 1; + } + } + var fracheight = 0; + var tested = 0; + var step_size = 0.5; + var towertop = slogzero; + var guess = Decimal.dZero; + while (step_size > 1e-16) { + tested = fracheight + step_size; + towertop = slogzero.pow(1 - tested).mul(slogone.pow(tested)); //Weighted geometric average + guess = Decimal.iteratedexp(base, estimate, towertop); + if (guess.eq(value)) return [new Decimal(estimate + tested), 2];else if (guess.lt(value)) fracheight += step_size; + step_size /= 2; + } + if (guess.neq_tolerance(value, 1e-7)) return [FC_NN(Number.NaN, Number.NaN, Number.NaN), 0]; + return [new Decimal(estimate + fracheight), 2]; + } + if (value.lt(upper) && value.gt(lower)) { + var _slogzero = lower.mul(upper).sqrt(); //Geometric mean of the two b^x = x solutions + var _slogone = baseD.pow(_slogzero); + var _estimate = 0; + if (value.lte(_slogzero) && value.gt(_slogone)) _estimate = 0;else if (value.lte(_slogone)) { + var _payload6 = _slogone; + _estimate = 1; + while (_payload6.gt(value)) { + _payload6 = baseD.pow(_payload6); + _estimate = _estimate + 1; + } + if (_payload6.lt(value)) { + _payload6 = _payload6.log(base); + _estimate = _estimate - 1; + } + } else if (value.gt(_slogzero)) { + var _payload7 = _slogzero; + _estimate = 0; + while (_payload7.lt(value)) { + _payload7 = _payload7.log(base); + _estimate = _estimate - 1; + } + } + var _fracheight = 0; + var _tested = 0; + var _step_size = 0.5; + var _towertop = _slogzero; + var _guess2 = Decimal.dZero; + while (_step_size > 1e-16) { + _tested = _fracheight + _step_size; + _towertop = _slogzero.pow(1 - _tested).mul(_slogone.pow(_tested)); //Weighted geometric average + _guess2 = Decimal.iteratedexp(base, _estimate, _towertop); + if (_guess2.eq(value)) return [new Decimal(_estimate + _tested), 1];else if (_guess2.gt(value)) _fracheight += _step_size; + _step_size /= 2; + } + if (_guess2.neq_tolerance(value, 1e-7)) return [FC_NN(Number.NaN, Number.NaN, Number.NaN), 0]; + return [new Decimal(_estimate + _fracheight), 1]; + } + throw new Error("Unhandled behavior in excess_slog"); + } }]); return Decimal; }(); @@ -4216,7 +4432,7 @@ Decimal.dTwo = FC_NN(1, 0, 2); Decimal.dTen = FC_NN(1, 0, 10); Decimal.dNaN = FC_NN(Number.NaN, Number.NaN, Number.NaN); Decimal.dInf = FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); -Decimal.dNegInf = FC_NN(-1, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY); +Decimal.dNegInf = FC_NN(-1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); Decimal.dNumberMax = FC(1, 0, Number.MAX_VALUE); Decimal.dNumberMin = FC(1, 0, Number.MIN_VALUE); Decimal.fromStringCache = new LRUCache(DEFAULT_FROM_STRING_CACHE_SIZE); diff --git a/break_eternity.esm.js b/break_eternity.esm.js index fe56416..e949d84 100644 --- a/break_eternity.esm.js +++ b/break_eternity.esm.js @@ -283,42 +283,53 @@ var f_gamma = function f_gamma(n) { var np = n; l = l + 1 / (12 * np); np = np * n2; - l = l + 1 / (360 * np); + l = l - 1 / (360 * np); np = np * n2; l = l + 1 / (1260 * np); np = np * n2; - l = l + 1 / (1680 * np); + l = l - 1 / (1680 * np); np = np * n2; l = l + 1 / (1188 * np); np = np * n2; - l = l + 691 / (360360 * np); + l = l - 691 / (360360 * np); np = np * n2; l = l + 7 / (1092 * np); np = np * n2; - l = l + 3617 / (122400 * np); + l = l - 3617 / (122400 * np); return Math.exp(l) / scal1; }; var _EXPN1 = 0.36787944117144232159553; // exp(-1) var OMEGA = 0.56714329040978387299997; // W(1, 0) //from https://math.stackexchange.com/a/465183 // The evaluation can become inaccurate very close to the branch point +// Evaluates W(x, 0) if principal is true, W(x, -1) if principal is false var f_lambertw = function f_lambertw(z) { var tol = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1e-10; + var principal = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var w; var wn; if (!Number.isFinite(z)) { return z; } - if (z === 0) { - return z; - } - if (z === 1) { - return OMEGA; - } - if (z < 10) { - w = 0; + if (principal) { + if (z === 0) { + return z; + } + if (z === 1) { + return OMEGA; + } + if (z < 10) { + w = 0; + } else { + w = Math.log(z) - Math.log(Math.log(z)); + } } else { - w = Math.log(z) - Math.log(Math.log(z)); + if (z === 0) return -Infinity; + if (z <= -0.1) { + w = -2; + } else { + w = Math.log(-z) - Math.log(-Math.log(-z)); + } } for (var i = 0; i < 100; ++i) { wn = (z * Math.exp(-w) + w * w) / (w + 1); @@ -335,22 +346,32 @@ var f_lambertw = function f_lambertw(z) { // The evaluation can become inaccurate very close to the branch point // at ``-1/e``. In some corner cases, `lambertw` might currently // fail to converge, or can end up on the wrong branch. +// Evaluates W(x, 0) if principal is true, W(x, -1) if principal is false function d_lambertw(z) { var tol = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1e-10; + var principal = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var w; var ew, wewz, wn; if (!Number.isFinite(z.mag)) { - return z; - } - if (z.eq(Decimal.dZero)) { - return z; + return new Decimal(z); } - if (z.eq(Decimal.dOne)) { - //Split out this case because the asymptotic series blows up - return Decimal.fromNumber(OMEGA); + if (principal) { + if (z.eq(Decimal.dZero)) { + return FC_NN(0, 0, 0); + } + if (z.eq(Decimal.dOne)) { + //Split out this case because the asymptotic series blows up + return Decimal.fromNumber(OMEGA); + } + //Get an initial guess for Halley's method + w = Decimal.ln(z); + } else { + if (z.eq(Decimal.dZero)) { + return FC_NN(-1, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY); + } + //Get an initial guess for Halley's method + w = Decimal.ln(z.neg()); } - //Get an initial guess for Halley's method - w = Decimal.ln(z); //Halley's method; see 5.9 in [1] for (var i = 0; i < 100; ++i) { ew = w.neg().exp(); @@ -489,7 +510,7 @@ var Decimal = /*#__PURE__*/function () { Any 0 is totally zero (0, 0, 0) and any NaN is totally NaN (NaN, NaN, NaN). Anything layer 0 has mag 0 OR mag > 1/9e15 and < 9e15. Anything layer 1 or higher has abs(mag) >= 15.954 and < 9e15. - Any positive infinity is (1, Infinity, Infinity) and any negative infinity is (-1, -Infinity, -Infinity). + Any positive infinity is (1, Infinity, Infinity) and any negative infinity is (-1, Infinity, Infinity). We will assume in calculations that all Decimals are either erroneous or satisfy these criteria. (Otherwise: Garbage in, garbage out.) */ //Any 0 is totally 0 @@ -506,13 +527,8 @@ var Decimal = /*#__PURE__*/function () { } //Handle infinities if (this.mag === Number.POSITIVE_INFINITY || this.layer === Number.POSITIVE_INFINITY || this.mag === Number.NEGATIVE_INFINITY || this.layer === Number.NEGATIVE_INFINITY) { - if (this.sign == 1) { - this.mag = Number.POSITIVE_INFINITY; - this.layer = Number.POSITIVE_INFINITY; - } else if (this.sign == -1) { - this.mag = Number.NEGATIVE_INFINITY; - this.layer = Number.NEGATIVE_INFINITY; - } + this.mag = Number.POSITIVE_INFINITY; + this.layer = Number.POSITIVE_INFINITY; return this; } //Handle shifting from layer 0 to negative layers. @@ -728,6 +744,11 @@ var Decimal = /*#__PURE__*/function () { var ptparts = value.split("pt"); if (ptparts.length === 2) { base = 10; + var negative = false; + if (ptparts[0][0] == "-") { + negative = true; + ptparts[0] = ptparts[0].slice(1); + } height = parseFloat(ptparts[0]); ptparts[1] = ptparts[1].replace("(", ""); ptparts[1] = ptparts[1].replace(")", ""); @@ -743,6 +764,7 @@ var Decimal = /*#__PURE__*/function () { if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } + if (negative) this.sign *= -1; return this; } } @@ -750,6 +772,11 @@ var Decimal = /*#__PURE__*/function () { ptparts = value.split("p"); if (ptparts.length === 2) { base = 10; + var _negative = false; + if (ptparts[0][0] == "-") { + _negative = true; + ptparts[0] = ptparts[0].slice(1); + } height = parseFloat(ptparts[0]); ptparts[1] = ptparts[1].replace("(", ""); ptparts[1] = ptparts[1].replace(")", ""); @@ -765,6 +792,7 @@ var Decimal = /*#__PURE__*/function () { if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } + if (_negative) this.sign *= -1; return this; } } @@ -772,6 +800,11 @@ var Decimal = /*#__PURE__*/function () { ptparts = value.split("f"); if (ptparts.length === 2) { base = 10; + var _negative2 = false; + if (ptparts[0][0] == "-") { + _negative2 = true; + ptparts[0] = ptparts[0].slice(1); + } ptparts[0] = ptparts[0].replace("(", ""); ptparts[0] = ptparts[0].replace(")", ""); var _payload4 = parseFloat(ptparts[0]); @@ -789,6 +822,7 @@ var Decimal = /*#__PURE__*/function () { if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } + if (_negative2) this.sign *= -1; return this; } } @@ -936,7 +970,7 @@ var Decimal = /*#__PURE__*/function () { if (this.mag === Number.POSITIVE_INFINITY && this.layer === Number.POSITIVE_INFINITY && this.sign === 1) { return Number.POSITIVE_INFINITY; } - if (this.mag === Number.NEGATIVE_INFINITY && this.layer === Number.NEGATIVE_INFINITY && this.sign === -1) { + if (this.mag === Number.POSITIVE_INFINITY && this.layer === Number.POSITIVE_INFINITY && this.sign === -1) { return Number.NEGATIVE_INFINITY; } if (!Number.isFinite(this.layer)) { @@ -986,7 +1020,7 @@ var Decimal = /*#__PURE__*/function () { if (isNaN(this.layer) || isNaN(this.sign) || isNaN(this.mag)) { return "NaN"; } - if (this.mag === Number.POSITIVE_INFINITY || this.layer === Number.POSITIVE_INFINITY || this.mag === Number.NEGATIVE_INFINITY || this.layer === Number.NEGATIVE_INFINITY) { + if (this.mag === Number.POSITIVE_INFINITY || this.layer === Number.POSITIVE_INFINITY) { return this.sign === 1 ? "Infinity" : "-Infinity"; } if (this.layer === 0) { @@ -1111,12 +1145,12 @@ var Decimal = /*#__PURE__*/function () { key: "round", value: function round() { if (this.mag < 0) { - return Decimal.dZero; + return FC_NN(0, 0, 0); } if (this.layer === 0) { return FC(this.sign, 0, Math.round(this.mag)); } - return this; + return new Decimal(this); } /** * "Rounds" the Decimal it's called on to the nearest integer that's less than or equal to it. @@ -1125,13 +1159,13 @@ var Decimal = /*#__PURE__*/function () { key: "floor", value: function floor() { if (this.mag < 0) { - if (this.sign === -1) return Decimal.dNegOne;else return Decimal.dZero; + if (this.sign === -1) return FC_NN(-1, 0, 1);else return FC_NN(0, 0, 0); } if (this.sign === -1) return this.neg().ceil().neg(); if (this.layer === 0) { return FC(this.sign, 0, Math.floor(this.mag)); } - return this; + return new Decimal(this); } /** * "Rounds" the Decimal it's called on to the nearest integer that's greater than or equal to it. @@ -1140,14 +1174,14 @@ var Decimal = /*#__PURE__*/function () { key: "ceil", value: function ceil() { if (this.mag < 0) { - if (this.sign === 1) return Decimal.dOne; //The ceiling function called on something tiny like 10^10^-100 should return 1, since 10^10^-100 is still greater than 0 - else return Decimal.dZero; + if (this.sign === 1) return FC_NN(1, 0, 1); //The ceiling function called on something tiny like 10^10^-100 should return 1, since 10^10^-100 is still greater than 0 + else return FC_NN(0, 0, 0); } if (this.sign === -1) return this.neg().floor().neg(); if (this.layer === 0) { return FC(this.sign, 0, Math.ceil(this.mag)); } - return this; + return new Decimal(this); } /** * Extracts the integer part of the Decimal and returns it. Behaves like floor on positive numbers, but behaves like ceiling on negative numbers. @@ -1156,12 +1190,12 @@ var Decimal = /*#__PURE__*/function () { key: "trunc", value: function trunc() { if (this.mag < 0) { - return Decimal.dZero; + return FC_NN(0, 0, 0); } if (this.layer === 0) { return FC(this.sign, 0, Math.trunc(this.mag)); } - return this; + return new Decimal(this); } /** * Addition: returns the sum of 'this' and 'value'. @@ -1170,19 +1204,23 @@ var Decimal = /*#__PURE__*/function () { key: "add", value: function add(value) { var decimal = D(value); + //Infinity + -Infinity = NaN + if (this.eq(Decimal.dInf) && decimal.eq(Decimal.dNegInf) || this.eq(Decimal.dNegInf) && decimal.eq(Decimal.dInf)) { + return FC_NN(Number.NaN, Number.NaN, Number.NaN); + } //inf/nan check if (!Number.isFinite(this.layer)) { - return this; + return new Decimal(this); } if (!Number.isFinite(decimal.layer)) { - return decimal; + return new Decimal(decimal); } //Special case - if one of the numbers is 0, return the other number. if (this.sign === 0) { - return decimal; + return new Decimal(decimal); } if (decimal.sign === 0) { - return this; + return new Decimal(this); } //Special case - Adding a number to its negation produces 0, no matter how large. if (this.sign === -decimal.sign && this.layer === decimal.layer && this.mag === decimal.mag) { @@ -1195,11 +1233,11 @@ var Decimal = /*#__PURE__*/function () { return this.maxabs(decimal); } if (Decimal.cmpabs(this, decimal) > 0) { - a = this; - b = decimal; + a = new Decimal(this); + b = new Decimal(decimal); } else { - a = decimal; - b = this; + a = new Decimal(decimal); + b = new Decimal(this); } if (a.layer === 0 && b.layer === 0) { return Decimal.fromNumber(a.sign * a.mag + b.sign * b.mag); @@ -1275,12 +1313,20 @@ var Decimal = /*#__PURE__*/function () { key: "mul", value: function mul(value) { var decimal = D(value); + // Infinity * -Infinity = -Infinity + if (this.eq(Decimal.dInf) && decimal.eq(Decimal.dNegInf) || this.eq(Decimal.dNegInf) && decimal.eq(Decimal.dInf)) { + return FC_NN(-1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); + } + //Infinity * 0 = NaN + if (this.mag == Number.POSITIVE_INFINITY && decimal.eq(Decimal.dZero) || this.eq(Decimal.dZero) && this.mag == Number.POSITIVE_INFINITY) { + return FC_NN(Number.NaN, Number.NaN, Number.NaN); + } //inf/nan check if (!Number.isFinite(this.layer)) { - return this; + return new Decimal(this); } if (!Number.isFinite(decimal.layer)) { - return decimal; + return new Decimal(decimal); } //Special case - if one of the numbers is 0, return 0. if (this.sign === 0 || decimal.sign === 0) { @@ -1294,11 +1340,11 @@ var Decimal = /*#__PURE__*/function () { var b; //Which number is bigger in terms of its multiplicative distance from 1? if (this.layer > decimal.layer || this.layer == decimal.layer && Math.abs(this.mag) > Math.abs(decimal.mag)) { - a = this; - b = decimal; + a = new Decimal(this); + b = new Decimal(decimal); } else { - a = decimal; - b = this; + a = new Decimal(decimal); + b = new Decimal(this); } if (a.layer === 0 && b.layer === 0) { return Decimal.fromNumber(a.sign * b.sign * a.mag * b.mag); @@ -1379,7 +1425,9 @@ var Decimal = /*#__PURE__*/function () { key: "recip", value: function recip() { if (this.mag === 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); + } else if (this.mag === Number.POSITIVE_INFINITY) { + return FC_NN(0, 0, 0); } else if (this.layer === 0) { return FC(this.sign, 0, 1 / this.mag); } else { @@ -1411,7 +1459,7 @@ var Decimal = /*#__PURE__*/function () { key: "mod", value: function mod(value) { var decimal = D(value).abs(); - if (decimal.eq(Decimal.dZero)) return Decimal.dZero; + if (decimal.eq(Decimal.dZero)) return FC_NN(0, 0, 0); var num_this = this.toNumber(); var num_decimal = decimal.toNumber(); //Special case: To avoid precision issues, if both numbers are valid JS numbers, just call % on those @@ -1420,11 +1468,11 @@ var Decimal = /*#__PURE__*/function () { } if (this.sub(decimal).eq(this)) { //decimal is too small to register to this - return Decimal.dZero; + return FC_NN(0, 0, 0); } if (decimal.sub(this).eq(decimal)) { //this is too small to register to decimal - return this; + return new Decimal(this); } if (this.sign == -1) return this.abs().mod(decimal).neg(); return this.sub(this.div(decimal).floor().mul(decimal)); @@ -1590,7 +1638,7 @@ var Decimal = /*#__PURE__*/function () { key: "max", value: function max(value) { var decimal = D(value); - return this.lt(decimal) ? decimal : this; + return this.lt(decimal) ? new Decimal(decimal) : new Decimal(this); } /** * Returns whichever of 'this' and 'value' is lower. @@ -1599,7 +1647,7 @@ var Decimal = /*#__PURE__*/function () { key: "min", value: function min(value) { var decimal = D(value); - return this.gt(decimal) ? decimal : this; + return this.gt(decimal) ? new Decimal(decimal) : new Decimal(this); } /** * Returns whichever of 'this' and 'value' has a larger absolute value. @@ -1608,7 +1656,7 @@ var Decimal = /*#__PURE__*/function () { key: "maxabs", value: function maxabs(value) { var decimal = D(value); - return this.cmpabs(decimal) < 0 ? decimal : this; + return this.cmpabs(decimal) < 0 ? new Decimal(decimal) : new Decimal(this); } /** * Returns whichever of 'this' and 'value' has a smaller absolute value. @@ -1617,7 +1665,7 @@ var Decimal = /*#__PURE__*/function () { key: "minabs", value: function minabs(value) { var decimal = D(value); - return this.cmpabs(decimal) > 0 ? decimal : this; + return this.cmpabs(decimal) > 0 ? new Decimal(decimal) : new Decimal(this); } /** * A combination of minimum and maximum: the value returned by clamp is normally 'this', but it won't go below 'min' and it won't go above 'max'. @@ -1792,7 +1840,7 @@ var Decimal = /*#__PURE__*/function () { key: "pLog10", value: function pLog10() { if (this.lt(Decimal.dZero)) { - return Decimal.dZero; + return FC_NN(0, 0, 0); } return this.log10(); } @@ -1803,7 +1851,7 @@ var Decimal = /*#__PURE__*/function () { key: "absLog10", value: function absLog10() { if (this.sign === 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } else if (this.layer > 0) { return FC(Math.sign(this.mag), this.layer - 1, Math.abs(this.mag)); } else { @@ -1818,7 +1866,7 @@ var Decimal = /*#__PURE__*/function () { key: "log10", value: function log10() { if (this.sign <= 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } else if (this.layer > 0) { return FC(Math.sign(this.mag), this.layer - 1, Math.abs(this.mag)); } else { @@ -1833,13 +1881,13 @@ var Decimal = /*#__PURE__*/function () { value: function log(base) { base = D(base); if (this.sign <= 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } if (base.sign <= 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } if (base.sign === 1 && base.layer === 0 && base.mag === 1) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } else if (this.layer === 0 && base.layer === 0) { return FC(this.sign, 0, Math.log(this.mag) / Math.log(base.mag)); } @@ -1852,7 +1900,7 @@ var Decimal = /*#__PURE__*/function () { key: "log2", value: function log2() { if (this.sign <= 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } else if (this.layer === 0) { return FC(this.sign, 0, Math.log2(this.mag)); } else if (this.layer === 1) { @@ -1870,7 +1918,7 @@ var Decimal = /*#__PURE__*/function () { key: "ln", value: function ln() { if (this.sign <= 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } else if (this.layer === 0) { return FC(this.sign, 0, Math.log(this.mag)); } else if (this.layer === 1) { @@ -1896,8 +1944,8 @@ var Decimal = /*#__PURE__*/function () { key: "pow", value: function pow(value) { var decimal = D(value); - var a = this; - var b = decimal; + var a = new Decimal(this); + var b = new Decimal(decimal); //special case: if a is 0, then return 0 (UNLESS b is 0, then return 1) if (a.sign === 0) { return b.eq(0) ? FC_NN(1, 0, 1) : a; @@ -1921,7 +1969,7 @@ var Decimal = /*#__PURE__*/function () { } else if (Math.abs(b.toNumber() % 2) % 2 === 0) { return result; } - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } return result; } @@ -1938,10 +1986,16 @@ var Decimal = /*#__PURE__*/function () { 3) positive sign, negative mag (e-15, ee-15): layer 0 case would have been handled in the Math.pow check, so just return 1 4) negative sign, negative mag (-e-15, -ee-15): layer 0 case would have been handled in the Math.pow check, so just return 1 */ + if (this.eq(Decimal.dInf)) { + return FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); + } + if (this.eq(Decimal.dNegInf)) { + return FC_NN(0, 0, 0); + } if (!Number.isFinite(this.layer) || !Number.isFinite(this.mag)) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } - var a = this; + var a = new Decimal(this); //handle layer 0 case - if no precision is lost just use Math.pow, else promote one layer if (a.layer === 0) { var newmag = Math.pow(10, a.sign * a.mag); @@ -1949,7 +2003,7 @@ var Decimal = /*#__PURE__*/function () { return FC(1, 0, newmag); } else { if (a.sign === 0) { - return Decimal.dOne; + return FC_NN(1, 0, 1); } else { a = FC_NN(a.sign, a.layer + 1, Math.log10(a.mag)); } @@ -1963,7 +2017,7 @@ var Decimal = /*#__PURE__*/function () { return FC(-a.sign, a.layer + 1, -a.mag); } //both the negative mag cases are identical: one +/- rounding error - return Decimal.dOne; + return FC_NN(1, 0, 1); } /** * Exponentiation: Returns the result of 'value' ^ 'this' (often written as 'value' ** 'this' in programming languages). @@ -2066,7 +2120,7 @@ var Decimal = /*#__PURE__*/function () { key: "exp", value: function exp() { if (this.mag < 0) { - return Decimal.dOne; + return FC_NN(1, 0, 1); } if (this.layer === 0 && this.mag <= 709.7) { return Decimal.fromNumber(Math.exp(this.sign * this.mag)); @@ -2146,7 +2200,7 @@ var Decimal = /*#__PURE__*/function () { } //1^^x == 1 if (this.eq(Decimal.dOne)) { - return Decimal.dOne; + return FC_NN(1, 0, 1); } //-1^^x == -1 if (this.eq(-1)) { @@ -2156,21 +2210,25 @@ var Decimal = /*#__PURE__*/function () { var this_num = this.toNumber(); //within the convergence range? if (this_num <= 1.44466786100976613366 && this_num >= 0.06598803584531253708) { + var negln = Decimal.ln(this).neg(); + //For bases above 1, b^x = x has two solutions. The lower solution is a stable equilibrium, the upper solution is an unstable equilibrium. + var lower = negln.lambertw().div(negln); + // However, if the base is below 1, there's only the stable equilibrium solution. + if (this_num < 1) return lower; + var upper = negln.lambertw(false).div(negln); //hotfix for the very edge of the number range not being handled properly if (this_num > 1.444667861009099) { - return Decimal.fromNumber(Math.E); + lower = upper = Decimal.fromNumber(Math.E); } - //Formula for infinite height power tower. - var negln = Decimal.ln(this).neg(); - return negln.lambertw().div(negln); + payload = D(payload); + if (payload.eq(upper)) return upper;else if (payload.lt(upper)) return lower;else return FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); } else if (this_num > 1.44466786100976613366) { //explodes to infinity - // TODO: replace this with Decimal.dInf - return Decimal.fromNumber(Number.POSITIVE_INFINITY); + return FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); } else { //0.06598803584531253708 > this_num >= 0: never converges //this_num < 0: quickly becomes a complex number - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } } //0^^x oscillates if we define 0^0 == 1 (which in javascript land we do), since then 0^^1 is 0, 0^^2 is 1, 0^^3 is 0, etc. payload is ignored @@ -2185,14 +2243,15 @@ var Decimal = /*#__PURE__*/function () { if (height < 0) { return Decimal.iteratedlog(payload, this, -height, linear); } - payload = D(payload); + payload = new Decimal(payload); var oldheight = height; height = Math.trunc(height); var fracheight = oldheight - height; - if (this.gt(Decimal.dZero) && this.lte(1.44466786100976613366) && (oldheight > 10000 || !linear)) { - //similar to 0^^n, flip-flops between two values, converging slowly (or if it's below 0.06598803584531253708, never. so once again, the fractional part at the end will be a linear approximation (TODO: again pending knowledge of how to approximate better, although tbh I think it should in reality just be NaN) - height = Math.min(10000, height); - for (var i = 0; i < height; ++i) { + if (this.gt(Decimal.dZero) && (this.lt(1) || this.lte(1.44466786100976613366) && payload.lte(Decimal.ln(this).neg().lambertw(false).div(Decimal.ln(this).neg()))) && (oldheight > 10000 || !linear)) { + //similar to 0^^n, flip-flops between two values, converging slowly (or if it's below 0.06598803584531253708, never). So once again, the fractional part at the beginning will be a linear approximation (TODO: again pending knowledge of how to approximate better, although tbh I think it should in reality just be NaN) + var limitheight = Math.min(10000, height); + if (payload.eq(Decimal.dOne)) payload = this.pow(fracheight);else if (this.lt(1)) payload = payload.pow(1 - fracheight).mul(this.pow(payload).pow(fracheight));else payload = payload.layeradd(fracheight, this); + for (var i = 0; i < limitheight; ++i) { var old_payload = payload; payload = this.pow(payload); //stop early if we converge @@ -2200,13 +2259,8 @@ var Decimal = /*#__PURE__*/function () { return payload; } } - if (fracheight != 0 || oldheight > 10000) { - var next_payload = this.pow(payload); - if (oldheight <= 10000 || Math.ceil(oldheight) % 2 == 0) { - return payload.mul(1 - fracheight).add(next_payload.mul(fracheight)); - } else { - return payload.mul(fracheight).add(next_payload.mul(1 - fracheight)); - } + if (oldheight > 10000 && Math.ceil(oldheight) % 2 == 1) { + return this.pow(payload); } return payload; } @@ -2228,6 +2282,8 @@ var Decimal = /*#__PURE__*/function () { } else { if (this.eq(10)) { payload = payload.layeradd10(fracheight, linear); + } else if (this.lt(1)) { + payload = payload.pow(1 - fracheight).mul(this.pow(payload).pow(fracheight)); } else { payload = payload.layeradd(fracheight, this, linear); } @@ -2311,6 +2367,7 @@ var Decimal = /*#__PURE__*/function () { if (base.eq(10)) { result = result.layeradd10(-fraction, linear); } else { + //I have no clue what a fractional times on a base below 1 should even mean, so I'm not going to bother - just let it be NaN (TODO: come up with what the answer actually should be) result = result.layeradd(-fraction, base, linear); } } @@ -2369,28 +2426,34 @@ var Decimal = /*#__PURE__*/function () { //special cases: //slog base 0 or lower is NaN if (base.lte(Decimal.dZero)) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //slog base 1 is NaN if (base.eq(Decimal.dOne)) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //need to handle these small, wobbling bases specially if (base.lt(Decimal.dOne)) { if (this.eq(Decimal.dOne)) { - return Decimal.dZero; + return FC_NN(0, 0, 0); } if (this.eq(Decimal.dZero)) { - return Decimal.dNegOne; + return FC_NN(-1, 0, 1); } //0 < this < 1: ambiguous (happens multiple times) //this < 0: impossible (as far as I can tell) //this > 1: partially complex (http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html base 0.25 for proof) - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //slog_n(0) is -1 if (this.mag < 0 || this.eq(Decimal.dZero)) { - return Decimal.dNegOne; + return FC_NN(-1, 0, 1); + } + if (base.lt(1.44466786100976613366)) { + var negln = Decimal.ln(base).neg(); + var infTower = negln.lambertw().div(negln); + if (this.eq(infTower)) return FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); + if (this.gt(infTower)) return FC_NN(Number.NaN, Number.NaN, Number.NaN); } var result = 0; var copy = Decimal.fromDecimal(this); @@ -2501,41 +2564,87 @@ var Decimal = /*#__PURE__*/function () { key: "layeradd", value: function layeradd(diff, base) { var linear = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; - var slogthis = this.slog(base).toNumber(); + var baseD = D(base); + if (baseD.gt(1) && baseD.lte(1.44466786100976613366)) { + var excessSlog = Decimal.excess_slog(this, base, linear); + var _slogthis = excessSlog[0].toNumber(); + var range = excessSlog[1]; + var _slogdest = _slogthis + diff; + var negln = Decimal.ln(base).neg(); + var lower = negln.lambertw().div(negln); + var upper = negln.lambertw(false).div(negln); + var slogzero = Decimal.dOne; + if (range == 1) slogzero = lower.mul(upper).sqrt();else if (range == 2) slogzero = upper.mul(2); + var slogone = baseD.pow(slogzero); + var wholeheight = Math.floor(_slogdest); + var fracheight = _slogdest - wholeheight; + var towertop = slogzero.pow(1 - fracheight).mul(slogone.pow(fracheight)); + return Decimal.tetrate(baseD, wholeheight, towertop, linear); //wholediff is a whole number so this is safe even if it ends up calling iteratedlog + } + + var slogthis = this.slog(base, 100, linear).toNumber(); var slogdest = slogthis + diff; if (slogdest >= 0) { return Decimal.tetrate(base, slogdest, Decimal.dOne, linear); } else if (!Number.isFinite(slogdest)) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } else if (slogdest >= -1) { return Decimal.log(Decimal.tetrate(base, slogdest + 1, Decimal.dOne, linear), base); } else { return Decimal.log(Decimal.log(Decimal.tetrate(base, slogdest + 2, Decimal.dOne, linear), base), base); } } + //Apparently having something be private but not static breaks everything + /** + * A strange version of slog for bases between 1 and e^1/e which can handle values above base^^Infinity. + * Returns a pair of a Decimal and a number, with the number always being 0, 1, or 2. The number indicates what range we're in: + * 0 means we're below the lower solution of b^x = x, and so the normal slog is used. + * 1 means we're between the two solutions of b^x = x, with the geometric mean of the two solutions arbitrarily chosen to be the value with a slog of 0. + * 2 means we're above the upper solution of b^x = x, with (upper solution * 2) arbitrarily chosen to be the value with a slog of 0. + * + * The values returned by this function don't really have much mathematical meaning, but the difference between two values does. + * Therefore, this function is kept private, but it's used for layeradd on these small bases. + */ + }, { + key: "lambertw", + value: /** * The Lambert W function, also called the omega function or product logarithm, is the solution W(x) === x*e^x. * https://en.wikipedia.org/wiki/Lambert_W_function + * + * This is a multi-valued function in the complex plane, but only two branches matter for real numbers: the "principal branch" W0, and the "non-principal branch" W_-1. + * W_0 works for any number >= -1/e, but W_-1 only works for nonpositive numbers >= -1/e. + * The "principal" parameter, which is true by default, decides which branch we're looking for: W_0 is used if principal is true, W_-1 is used if principal is false. */ //Some special values, for testing: https://en.wikipedia.org/wiki/Lambert_W_function#Special_values - }, { - key: "lambertw", - value: function lambertw() { + function lambertw() { + var principal = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; if (this.lt(-0.3678794411710499)) { - throw Error("lambertw is unimplemented for results less than -1, sorry!"); - } else if (this.mag < 0) { - return Decimal.fromNumber(f_lambertw(this.toNumber())); - } else if (this.layer === 0) { - return Decimal.fromNumber(f_lambertw(this.sign * this.mag)); - } else if (this.layer === 1) { - return d_lambertw(this); - } else if (this.layer === 2) { - return d_lambertw(this); - } - if (this.layer >= 3) { - return FC_NN(this.sign, this.layer - 1, this.mag); + return FC_NN(Number.NaN, Number.NaN, Number.NaN); //complex + } else if (principal) { + if (this.abs().lt("1e-300")) return new Decimal(this);else if (this.mag < 0) { + return Decimal.fromNumber(f_lambertw(this.toNumber())); + } else if (this.layer === 0) { + return Decimal.fromNumber(f_lambertw(this.sign * this.mag)); + } else if (this.lt("eee15")) { + return d_lambertw(this); + } else { + // Numbers this large would sometimes fail to converge using d_lambertw, and at this size this.ln() is close enough + return this.ln(); + } + } else { + if (this.sign === 1) { + return FC_NN(Number.NaN, Number.NaN, Number.NaN); //complex + } + + if (this.layer === 0) { + return Decimal.fromNumber(f_lambertw(this.sign * this.mag, 1e-10, false)); + } else if (this.layer == 1) { + return d_lambertw(this, 1e-10, false); + } else { + return this.neg().recip().lambertw().neg(); + } } - throw "Unhandled behavior in lambertw()"; } /** * The super square-root function - what number, tetrated to height 2, equals 'this'? https://en.wikipedia.org/wiki/Tetration#Super-root @@ -2561,10 +2670,10 @@ var Decimal = /*#__PURE__*/function () { return this; } if (this.eq(Decimal.dInf)) { - return Decimal.dInf; + return FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); } if (!this.isFinite()) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //Using linear approximation, x^^n = x^n if 0 < n < 1 if (degree > 0 && degree < 1) { @@ -2576,7 +2685,7 @@ var Decimal = /*#__PURE__*/function () { } //Super roots with -1 <= degree < 0 have either no solution or infinitely many solutions, and tetration with height <= -2 returns NaN, so super roots of degree <= -2 don't work if (degree <= 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //Infinite degree super-root is x^(1/x) between 1/e <= x <= e, undefined otherwise if (degree == Number.POSITIVE_INFINITY) { @@ -2584,20 +2693,20 @@ var Decimal = /*#__PURE__*/function () { if (this_num < Math.E && this_num > _EXPN1) { return this.pow(this.recip()); } else { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } } //Special case: any super-root of 1 is 1 if (this.eq(1)) { - return Decimal.dOne; + return FC_NN(1, 0, 1); } //TODO: base < 0 (It'll probably be NaN anyway) if (this.lt(0)) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //Treat all numbers of layer <= -2 as zero, because they effectively are if (this.lte("1ee-16")) { - if (degree % 2 == 1) return this;else return Decimal.dNaN; + if (degree % 2 == 1) return new Decimal(this);else return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //this > 1 if (this.gt(1)) { @@ -2789,7 +2898,7 @@ var Decimal = /*#__PURE__*/function () { if (_lower.eq(FC(1, 10, 1))) _guess = _upper.mul(2);else _guess = _lower.add(_upper).div(2); if (Decimal.pow(10, _guess).recip().tetrate(degree, 1, true).gt(this)) _upper = _guess;else _lower = _guess; if (_guess.eq(_previous)) _loopGoing = false;else _previous = _guess; - if (_upper.gt("1e18")) return Decimal.dNaN; + if (_upper.gt("1e18")) return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //using guess.neq(minimum) led to imprecision errors, so here's a fixed version of that if (!_guess.eq_tolerance(minimum, 1e-15)) { @@ -2799,7 +2908,7 @@ var Decimal = /*#__PURE__*/function () { //Check if the root is in the zero range. if (maximum.eq(FC(1, 10, 1))) { //There is no zero range, so the super root doesn't exist - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } _lower = FC(1, 10, 1); _upper = maximum; @@ -2810,7 +2919,7 @@ var Decimal = /*#__PURE__*/function () { if (_lower.eq(FC(1, 10, 1))) _guess = _upper.mul(2);else _guess = _lower.add(_upper).div(2); if (Decimal.pow(10, _guess).recip().tetrate(degree, 1, true).gt(this)) _upper = _guess;else _lower = _guess; if (_guess.eq(_previous)) _loopGoing = false;else _previous = _guess; - if (_upper.gt("1e18")) return Decimal.dNaN; + if (_upper.gt("1e18")) return FC_NN(Number.NaN, Number.NaN, Number.NaN); } return _guess.pow10().recip(); } @@ -2833,7 +2942,7 @@ var Decimal = /*#__PURE__*/function () { var height = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 2; var payload = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : FC_NN(1, 0, 1); var linear = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; - payload = D(payload); + payload = new Decimal(payload); var oldheight = height; height = Math.trunc(height); var fracheight = oldheight - height; @@ -2871,7 +2980,7 @@ var Decimal = /*#__PURE__*/function () { key: "sin", value: function sin() { if (this.mag < 0) { - return this; + return new Decimal(this); } if (this.layer === 0) { return Decimal.fromNumber(Math.sin(this.sign * this.mag)); @@ -2885,7 +2994,7 @@ var Decimal = /*#__PURE__*/function () { key: "cos", value: function cos() { if (this.mag < 0) { - return Decimal.dOne; + return FC_NN(1, 0, 1); } if (this.layer === 0) { return Decimal.fromNumber(Math.cos(this.sign * this.mag)); @@ -2899,7 +3008,7 @@ var Decimal = /*#__PURE__*/function () { key: "tan", value: function tan() { if (this.mag < 0) { - return this; + return new Decimal(this); } if (this.layer === 0) { return Decimal.fromNumber(Math.tan(this.sign * this.mag)); @@ -2913,7 +3022,7 @@ var Decimal = /*#__PURE__*/function () { key: "asin", value: function asin() { if (this.mag < 0) { - return this; + return new Decimal(this); } if (this.layer === 0) { return Decimal.fromNumber(Math.asin(this.sign * this.mag)); @@ -2941,7 +3050,7 @@ var Decimal = /*#__PURE__*/function () { key: "atan", value: function atan() { if (this.mag < 0) { - return this; + return new Decimal(this); } if (this.layer === 0) { return Decimal.fromNumber(Math.atan(this.sign * this.mag)); @@ -3006,7 +3115,7 @@ var Decimal = /*#__PURE__*/function () { key: "ascensionPenalty", value: function ascensionPenalty(ascensions) { if (ascensions === 0) { - return this; + return new Decimal(this); } return this.root(Decimal.pow(10, ascensions)); } @@ -3128,7 +3237,7 @@ var Decimal = /*#__PURE__*/function () { // This should never happen... but some users like Prestige Tree Rewritten // pass undefined values in as DecimalSources, so we should handle this // case to not break them. - return Decimal.dZero; + return FC_NN(0, 0, 0); } } /** @@ -3891,11 +4000,15 @@ var Decimal = /*#__PURE__*/function () { /** * The Lambert W function, also called the omega function or product logarithm, is the solution W(x) === x*e^x. * https://en.wikipedia.org/wiki/Lambert_W_function + * + * This is a multi-valued function in the complex plane, but only two branches matter for real numbers: the "principal branch" W0, and the "non-principal branch" W_-1. + * W_0 works for any number >= -1/e, but W_-1 only works for negative numbers >= -1/e. + * The "principal" parameter, which is true by default, decides which branch we're looking for: W_0 is used if principal is true, W_-1 is used if principal is false. */ }, { key: "lambertw", - value: function lambertw(value) { - return D(value).lambertw(); + value: function lambertw(value, principal) { + return D(value).lambertw(principal); } /** * The super square-root function - what number, tetrated to height 2, equals 'value'? https://en.wikipedia.org/wiki/Tetration#Super-root @@ -4204,6 +4317,109 @@ var Decimal = /*#__PURE__*/function () { return Math.pow(base, Math.log(lower) / Math.log(base) * (1 - frac) + Math.log(upper) / Math.log(base) * frac); } } + }, { + key: "excess_slog", + value: function excess_slog(value, base) { + var linear = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + value = D(value); + base = D(base); + var baseD = base; + base = base.toNumber(); + if (base == 1 || base <= 0) return [FC_NN(Number.NaN, Number.NaN, Number.NaN), 0]; + if (base > 1.44466786100976613366) return [value.slog(base, 100, linear), 0]; + var negln = Decimal.ln(base).neg(); + var lower = negln.lambertw().div(negln); + var upper = Decimal.dInf; + if (base > 1) upper = negln.lambertw(false).div(negln); + if (base > 1.444667861009099) { + lower = upper = Decimal.fromNumber(Math.E); + } + if (value.lt(lower)) return [value.slog(base, 100, linear), 0]; + if (value.eq(lower)) return [FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY), 0]; + if (value.eq(upper)) return [FC_NN(1, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY), 2]; + if (value.gt(upper)) { + var slogzero = upper.mul(2); + var slogone = baseD.pow(slogzero); + var estimate = 0; + if (value.gte(slogzero) && value.lt(slogone)) estimate = 0;else if (value.gte(slogone)) { + var payload = slogone; + estimate = 1; + while (payload.lt(value)) { + payload = baseD.pow(payload); + estimate = estimate + 1; + if (payload.layer > 3) { + var layersleft = Math.floor(value.layer - payload.layer + 1); + payload = baseD.iteratedexp(layersleft, payload, linear); + estimate = estimate + layersleft; + } + } + if (payload.gt(value)) { + payload = payload.log(base); + estimate = estimate - 1; + } + } else if (value.lt(slogzero)) { + var _payload5 = slogzero; + estimate = 0; + while (_payload5.gt(value)) { + _payload5 = _payload5.log(base); + estimate = estimate - 1; + } + } + var fracheight = 0; + var tested = 0; + var step_size = 0.5; + var towertop = slogzero; + var guess = Decimal.dZero; + while (step_size > 1e-16) { + tested = fracheight + step_size; + towertop = slogzero.pow(1 - tested).mul(slogone.pow(tested)); //Weighted geometric average + guess = Decimal.iteratedexp(base, estimate, towertop); + if (guess.eq(value)) return [new Decimal(estimate + tested), 2];else if (guess.lt(value)) fracheight += step_size; + step_size /= 2; + } + if (guess.neq_tolerance(value, 1e-7)) return [FC_NN(Number.NaN, Number.NaN, Number.NaN), 0]; + return [new Decimal(estimate + fracheight), 2]; + } + if (value.lt(upper) && value.gt(lower)) { + var _slogzero = lower.mul(upper).sqrt(); //Geometric mean of the two b^x = x solutions + var _slogone = baseD.pow(_slogzero); + var _estimate = 0; + if (value.lte(_slogzero) && value.gt(_slogone)) _estimate = 0;else if (value.lte(_slogone)) { + var _payload6 = _slogone; + _estimate = 1; + while (_payload6.gt(value)) { + _payload6 = baseD.pow(_payload6); + _estimate = _estimate + 1; + } + if (_payload6.lt(value)) { + _payload6 = _payload6.log(base); + _estimate = _estimate - 1; + } + } else if (value.gt(_slogzero)) { + var _payload7 = _slogzero; + _estimate = 0; + while (_payload7.lt(value)) { + _payload7 = _payload7.log(base); + _estimate = _estimate - 1; + } + } + var _fracheight = 0; + var _tested = 0; + var _step_size = 0.5; + var _towertop = _slogzero; + var _guess2 = Decimal.dZero; + while (_step_size > 1e-16) { + _tested = _fracheight + _step_size; + _towertop = _slogzero.pow(1 - _tested).mul(_slogone.pow(_tested)); //Weighted geometric average + _guess2 = Decimal.iteratedexp(base, _estimate, _towertop); + if (_guess2.eq(value)) return [new Decimal(_estimate + _tested), 1];else if (_guess2.gt(value)) _fracheight += _step_size; + _step_size /= 2; + } + if (_guess2.neq_tolerance(value, 1e-7)) return [FC_NN(Number.NaN, Number.NaN, Number.NaN), 0]; + return [new Decimal(_estimate + _fracheight), 1]; + } + throw new Error("Unhandled behavior in excess_slog"); + } }]); return Decimal; }(); @@ -4214,7 +4430,7 @@ Decimal.dTwo = FC_NN(1, 0, 2); Decimal.dTen = FC_NN(1, 0, 10); Decimal.dNaN = FC_NN(Number.NaN, Number.NaN, Number.NaN); Decimal.dInf = FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); -Decimal.dNegInf = FC_NN(-1, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY); +Decimal.dNegInf = FC_NN(-1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); Decimal.dNumberMax = FC(1, 0, Number.MAX_VALUE); Decimal.dNumberMin = FC(1, 0, Number.MIN_VALUE); Decimal.fromStringCache = new LRUCache(DEFAULT_FROM_STRING_CACHE_SIZE); diff --git a/break_eternity.js b/break_eternity.js index 6aa091a..928ab01 100644 --- a/break_eternity.js +++ b/break_eternity.js @@ -289,42 +289,53 @@ var np = n; l = l + 1 / (12 * np); np = np * n2; - l = l + 1 / (360 * np); + l = l - 1 / (360 * np); np = np * n2; l = l + 1 / (1260 * np); np = np * n2; - l = l + 1 / (1680 * np); + l = l - 1 / (1680 * np); np = np * n2; l = l + 1 / (1188 * np); np = np * n2; - l = l + 691 / (360360 * np); + l = l - 691 / (360360 * np); np = np * n2; l = l + 7 / (1092 * np); np = np * n2; - l = l + 3617 / (122400 * np); + l = l - 3617 / (122400 * np); return Math.exp(l) / scal1; }; var _EXPN1 = 0.36787944117144232159553; // exp(-1) var OMEGA = 0.56714329040978387299997; // W(1, 0) //from https://math.stackexchange.com/a/465183 // The evaluation can become inaccurate very close to the branch point + // Evaluates W(x, 0) if principal is true, W(x, -1) if principal is false var f_lambertw = function f_lambertw(z) { var tol = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1e-10; + var principal = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var w; var wn; if (!Number.isFinite(z)) { return z; } - if (z === 0) { - return z; - } - if (z === 1) { - return OMEGA; - } - if (z < 10) { - w = 0; + if (principal) { + if (z === 0) { + return z; + } + if (z === 1) { + return OMEGA; + } + if (z < 10) { + w = 0; + } else { + w = Math.log(z) - Math.log(Math.log(z)); + } } else { - w = Math.log(z) - Math.log(Math.log(z)); + if (z === 0) return -Infinity; + if (z <= -0.1) { + w = -2; + } else { + w = Math.log(-z) - Math.log(-Math.log(-z)); + } } for (var i = 0; i < 100; ++i) { wn = (z * Math.exp(-w) + w * w) / (w + 1); @@ -341,22 +352,32 @@ // The evaluation can become inaccurate very close to the branch point // at ``-1/e``. In some corner cases, `lambertw` might currently // fail to converge, or can end up on the wrong branch. + // Evaluates W(x, 0) if principal is true, W(x, -1) if principal is false function d_lambertw(z) { var tol = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1e-10; + var principal = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var w; var ew, wewz, wn; if (!Number.isFinite(z.mag)) { - return z; - } - if (z.eq(Decimal.dZero)) { - return z; + return new Decimal(z); } - if (z.eq(Decimal.dOne)) { - //Split out this case because the asymptotic series blows up - return Decimal.fromNumber(OMEGA); + if (principal) { + if (z.eq(Decimal.dZero)) { + return FC_NN(0, 0, 0); + } + if (z.eq(Decimal.dOne)) { + //Split out this case because the asymptotic series blows up + return Decimal.fromNumber(OMEGA); + } + //Get an initial guess for Halley's method + w = Decimal.ln(z); + } else { + if (z.eq(Decimal.dZero)) { + return FC_NN(-1, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY); + } + //Get an initial guess for Halley's method + w = Decimal.ln(z.neg()); } - //Get an initial guess for Halley's method - w = Decimal.ln(z); //Halley's method; see 5.9 in [1] for (var i = 0; i < 100; ++i) { ew = w.neg().exp(); @@ -495,7 +516,7 @@ Any 0 is totally zero (0, 0, 0) and any NaN is totally NaN (NaN, NaN, NaN). Anything layer 0 has mag 0 OR mag > 1/9e15 and < 9e15. Anything layer 1 or higher has abs(mag) >= 15.954 and < 9e15. - Any positive infinity is (1, Infinity, Infinity) and any negative infinity is (-1, -Infinity, -Infinity). + Any positive infinity is (1, Infinity, Infinity) and any negative infinity is (-1, Infinity, Infinity). We will assume in calculations that all Decimals are either erroneous or satisfy these criteria. (Otherwise: Garbage in, garbage out.) */ //Any 0 is totally 0 @@ -512,13 +533,8 @@ } //Handle infinities if (this.mag === Number.POSITIVE_INFINITY || this.layer === Number.POSITIVE_INFINITY || this.mag === Number.NEGATIVE_INFINITY || this.layer === Number.NEGATIVE_INFINITY) { - if (this.sign == 1) { - this.mag = Number.POSITIVE_INFINITY; - this.layer = Number.POSITIVE_INFINITY; - } else if (this.sign == -1) { - this.mag = Number.NEGATIVE_INFINITY; - this.layer = Number.NEGATIVE_INFINITY; - } + this.mag = Number.POSITIVE_INFINITY; + this.layer = Number.POSITIVE_INFINITY; return this; } //Handle shifting from layer 0 to negative layers. @@ -734,6 +750,11 @@ var ptparts = value.split("pt"); if (ptparts.length === 2) { base = 10; + var negative = false; + if (ptparts[0][0] == "-") { + negative = true; + ptparts[0] = ptparts[0].slice(1); + } height = parseFloat(ptparts[0]); ptparts[1] = ptparts[1].replace("(", ""); ptparts[1] = ptparts[1].replace(")", ""); @@ -749,6 +770,7 @@ if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } + if (negative) this.sign *= -1; return this; } } @@ -756,6 +778,11 @@ ptparts = value.split("p"); if (ptparts.length === 2) { base = 10; + var _negative = false; + if (ptparts[0][0] == "-") { + _negative = true; + ptparts[0] = ptparts[0].slice(1); + } height = parseFloat(ptparts[0]); ptparts[1] = ptparts[1].replace("(", ""); ptparts[1] = ptparts[1].replace(")", ""); @@ -771,6 +798,7 @@ if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } + if (_negative) this.sign *= -1; return this; } } @@ -778,6 +806,11 @@ ptparts = value.split("f"); if (ptparts.length === 2) { base = 10; + var _negative2 = false; + if (ptparts[0][0] == "-") { + _negative2 = true; + ptparts[0] = ptparts[0].slice(1); + } ptparts[0] = ptparts[0].replace("(", ""); ptparts[0] = ptparts[0].replace(")", ""); var _payload4 = parseFloat(ptparts[0]); @@ -795,6 +828,7 @@ if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } + if (_negative2) this.sign *= -1; return this; } } @@ -942,7 +976,7 @@ if (this.mag === Number.POSITIVE_INFINITY && this.layer === Number.POSITIVE_INFINITY && this.sign === 1) { return Number.POSITIVE_INFINITY; } - if (this.mag === Number.NEGATIVE_INFINITY && this.layer === Number.NEGATIVE_INFINITY && this.sign === -1) { + if (this.mag === Number.POSITIVE_INFINITY && this.layer === Number.POSITIVE_INFINITY && this.sign === -1) { return Number.NEGATIVE_INFINITY; } if (!Number.isFinite(this.layer)) { @@ -992,7 +1026,7 @@ if (isNaN(this.layer) || isNaN(this.sign) || isNaN(this.mag)) { return "NaN"; } - if (this.mag === Number.POSITIVE_INFINITY || this.layer === Number.POSITIVE_INFINITY || this.mag === Number.NEGATIVE_INFINITY || this.layer === Number.NEGATIVE_INFINITY) { + if (this.mag === Number.POSITIVE_INFINITY || this.layer === Number.POSITIVE_INFINITY) { return this.sign === 1 ? "Infinity" : "-Infinity"; } if (this.layer === 0) { @@ -1117,12 +1151,12 @@ key: "round", value: function round() { if (this.mag < 0) { - return Decimal.dZero; + return FC_NN(0, 0, 0); } if (this.layer === 0) { return FC(this.sign, 0, Math.round(this.mag)); } - return this; + return new Decimal(this); } /** * "Rounds" the Decimal it's called on to the nearest integer that's less than or equal to it. @@ -1131,13 +1165,13 @@ key: "floor", value: function floor() { if (this.mag < 0) { - if (this.sign === -1) return Decimal.dNegOne;else return Decimal.dZero; + if (this.sign === -1) return FC_NN(-1, 0, 1);else return FC_NN(0, 0, 0); } if (this.sign === -1) return this.neg().ceil().neg(); if (this.layer === 0) { return FC(this.sign, 0, Math.floor(this.mag)); } - return this; + return new Decimal(this); } /** * "Rounds" the Decimal it's called on to the nearest integer that's greater than or equal to it. @@ -1146,14 +1180,14 @@ key: "ceil", value: function ceil() { if (this.mag < 0) { - if (this.sign === 1) return Decimal.dOne; //The ceiling function called on something tiny like 10^10^-100 should return 1, since 10^10^-100 is still greater than 0 - else return Decimal.dZero; + if (this.sign === 1) return FC_NN(1, 0, 1); //The ceiling function called on something tiny like 10^10^-100 should return 1, since 10^10^-100 is still greater than 0 + else return FC_NN(0, 0, 0); } if (this.sign === -1) return this.neg().floor().neg(); if (this.layer === 0) { return FC(this.sign, 0, Math.ceil(this.mag)); } - return this; + return new Decimal(this); } /** * Extracts the integer part of the Decimal and returns it. Behaves like floor on positive numbers, but behaves like ceiling on negative numbers. @@ -1162,12 +1196,12 @@ key: "trunc", value: function trunc() { if (this.mag < 0) { - return Decimal.dZero; + return FC_NN(0, 0, 0); } if (this.layer === 0) { return FC(this.sign, 0, Math.trunc(this.mag)); } - return this; + return new Decimal(this); } /** * Addition: returns the sum of 'this' and 'value'. @@ -1176,19 +1210,23 @@ key: "add", value: function add(value) { var decimal = D(value); + //Infinity + -Infinity = NaN + if (this.eq(Decimal.dInf) && decimal.eq(Decimal.dNegInf) || this.eq(Decimal.dNegInf) && decimal.eq(Decimal.dInf)) { + return FC_NN(Number.NaN, Number.NaN, Number.NaN); + } //inf/nan check if (!Number.isFinite(this.layer)) { - return this; + return new Decimal(this); } if (!Number.isFinite(decimal.layer)) { - return decimal; + return new Decimal(decimal); } //Special case - if one of the numbers is 0, return the other number. if (this.sign === 0) { - return decimal; + return new Decimal(decimal); } if (decimal.sign === 0) { - return this; + return new Decimal(this); } //Special case - Adding a number to its negation produces 0, no matter how large. if (this.sign === -decimal.sign && this.layer === decimal.layer && this.mag === decimal.mag) { @@ -1201,11 +1239,11 @@ return this.maxabs(decimal); } if (Decimal.cmpabs(this, decimal) > 0) { - a = this; - b = decimal; + a = new Decimal(this); + b = new Decimal(decimal); } else { - a = decimal; - b = this; + a = new Decimal(decimal); + b = new Decimal(this); } if (a.layer === 0 && b.layer === 0) { return Decimal.fromNumber(a.sign * a.mag + b.sign * b.mag); @@ -1281,12 +1319,20 @@ key: "mul", value: function mul(value) { var decimal = D(value); + // Infinity * -Infinity = -Infinity + if (this.eq(Decimal.dInf) && decimal.eq(Decimal.dNegInf) || this.eq(Decimal.dNegInf) && decimal.eq(Decimal.dInf)) { + return FC_NN(-1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); + } + //Infinity * 0 = NaN + if (this.mag == Number.POSITIVE_INFINITY && decimal.eq(Decimal.dZero) || this.eq(Decimal.dZero) && this.mag == Number.POSITIVE_INFINITY) { + return FC_NN(Number.NaN, Number.NaN, Number.NaN); + } //inf/nan check if (!Number.isFinite(this.layer)) { - return this; + return new Decimal(this); } if (!Number.isFinite(decimal.layer)) { - return decimal; + return new Decimal(decimal); } //Special case - if one of the numbers is 0, return 0. if (this.sign === 0 || decimal.sign === 0) { @@ -1300,11 +1346,11 @@ var b; //Which number is bigger in terms of its multiplicative distance from 1? if (this.layer > decimal.layer || this.layer == decimal.layer && Math.abs(this.mag) > Math.abs(decimal.mag)) { - a = this; - b = decimal; + a = new Decimal(this); + b = new Decimal(decimal); } else { - a = decimal; - b = this; + a = new Decimal(decimal); + b = new Decimal(this); } if (a.layer === 0 && b.layer === 0) { return Decimal.fromNumber(a.sign * b.sign * a.mag * b.mag); @@ -1385,7 +1431,9 @@ key: "recip", value: function recip() { if (this.mag === 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); + } else if (this.mag === Number.POSITIVE_INFINITY) { + return FC_NN(0, 0, 0); } else if (this.layer === 0) { return FC(this.sign, 0, 1 / this.mag); } else { @@ -1417,7 +1465,7 @@ key: "mod", value: function mod(value) { var decimal = D(value).abs(); - if (decimal.eq(Decimal.dZero)) return Decimal.dZero; + if (decimal.eq(Decimal.dZero)) return FC_NN(0, 0, 0); var num_this = this.toNumber(); var num_decimal = decimal.toNumber(); //Special case: To avoid precision issues, if both numbers are valid JS numbers, just call % on those @@ -1426,11 +1474,11 @@ } if (this.sub(decimal).eq(this)) { //decimal is too small to register to this - return Decimal.dZero; + return FC_NN(0, 0, 0); } if (decimal.sub(this).eq(decimal)) { //this is too small to register to decimal - return this; + return new Decimal(this); } if (this.sign == -1) return this.abs().mod(decimal).neg(); return this.sub(this.div(decimal).floor().mul(decimal)); @@ -1596,7 +1644,7 @@ key: "max", value: function max(value) { var decimal = D(value); - return this.lt(decimal) ? decimal : this; + return this.lt(decimal) ? new Decimal(decimal) : new Decimal(this); } /** * Returns whichever of 'this' and 'value' is lower. @@ -1605,7 +1653,7 @@ key: "min", value: function min(value) { var decimal = D(value); - return this.gt(decimal) ? decimal : this; + return this.gt(decimal) ? new Decimal(decimal) : new Decimal(this); } /** * Returns whichever of 'this' and 'value' has a larger absolute value. @@ -1614,7 +1662,7 @@ key: "maxabs", value: function maxabs(value) { var decimal = D(value); - return this.cmpabs(decimal) < 0 ? decimal : this; + return this.cmpabs(decimal) < 0 ? new Decimal(decimal) : new Decimal(this); } /** * Returns whichever of 'this' and 'value' has a smaller absolute value. @@ -1623,7 +1671,7 @@ key: "minabs", value: function minabs(value) { var decimal = D(value); - return this.cmpabs(decimal) > 0 ? decimal : this; + return this.cmpabs(decimal) > 0 ? new Decimal(decimal) : new Decimal(this); } /** * A combination of minimum and maximum: the value returned by clamp is normally 'this', but it won't go below 'min' and it won't go above 'max'. @@ -1798,7 +1846,7 @@ key: "pLog10", value: function pLog10() { if (this.lt(Decimal.dZero)) { - return Decimal.dZero; + return FC_NN(0, 0, 0); } return this.log10(); } @@ -1809,7 +1857,7 @@ key: "absLog10", value: function absLog10() { if (this.sign === 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } else if (this.layer > 0) { return FC(Math.sign(this.mag), this.layer - 1, Math.abs(this.mag)); } else { @@ -1824,7 +1872,7 @@ key: "log10", value: function log10() { if (this.sign <= 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } else if (this.layer > 0) { return FC(Math.sign(this.mag), this.layer - 1, Math.abs(this.mag)); } else { @@ -1839,13 +1887,13 @@ value: function log(base) { base = D(base); if (this.sign <= 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } if (base.sign <= 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } if (base.sign === 1 && base.layer === 0 && base.mag === 1) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } else if (this.layer === 0 && base.layer === 0) { return FC(this.sign, 0, Math.log(this.mag) / Math.log(base.mag)); } @@ -1858,7 +1906,7 @@ key: "log2", value: function log2() { if (this.sign <= 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } else if (this.layer === 0) { return FC(this.sign, 0, Math.log2(this.mag)); } else if (this.layer === 1) { @@ -1876,7 +1924,7 @@ key: "ln", value: function ln() { if (this.sign <= 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } else if (this.layer === 0) { return FC(this.sign, 0, Math.log(this.mag)); } else if (this.layer === 1) { @@ -1902,8 +1950,8 @@ key: "pow", value: function pow(value) { var decimal = D(value); - var a = this; - var b = decimal; + var a = new Decimal(this); + var b = new Decimal(decimal); //special case: if a is 0, then return 0 (UNLESS b is 0, then return 1) if (a.sign === 0) { return b.eq(0) ? FC_NN(1, 0, 1) : a; @@ -1927,7 +1975,7 @@ } else if (Math.abs(b.toNumber() % 2) % 2 === 0) { return result; } - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } return result; } @@ -1944,10 +1992,16 @@ 3) positive sign, negative mag (e-15, ee-15): layer 0 case would have been handled in the Math.pow check, so just return 1 4) negative sign, negative mag (-e-15, -ee-15): layer 0 case would have been handled in the Math.pow check, so just return 1 */ + if (this.eq(Decimal.dInf)) { + return FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); + } + if (this.eq(Decimal.dNegInf)) { + return FC_NN(0, 0, 0); + } if (!Number.isFinite(this.layer) || !Number.isFinite(this.mag)) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } - var a = this; + var a = new Decimal(this); //handle layer 0 case - if no precision is lost just use Math.pow, else promote one layer if (a.layer === 0) { var newmag = Math.pow(10, a.sign * a.mag); @@ -1955,7 +2009,7 @@ return FC(1, 0, newmag); } else { if (a.sign === 0) { - return Decimal.dOne; + return FC_NN(1, 0, 1); } else { a = FC_NN(a.sign, a.layer + 1, Math.log10(a.mag)); } @@ -1969,7 +2023,7 @@ return FC(-a.sign, a.layer + 1, -a.mag); } //both the negative mag cases are identical: one +/- rounding error - return Decimal.dOne; + return FC_NN(1, 0, 1); } /** * Exponentiation: Returns the result of 'value' ^ 'this' (often written as 'value' ** 'this' in programming languages). @@ -2072,7 +2126,7 @@ key: "exp", value: function exp() { if (this.mag < 0) { - return Decimal.dOne; + return FC_NN(1, 0, 1); } if (this.layer === 0 && this.mag <= 709.7) { return Decimal.fromNumber(Math.exp(this.sign * this.mag)); @@ -2152,7 +2206,7 @@ } //1^^x == 1 if (this.eq(Decimal.dOne)) { - return Decimal.dOne; + return FC_NN(1, 0, 1); } //-1^^x == -1 if (this.eq(-1)) { @@ -2162,21 +2216,25 @@ var this_num = this.toNumber(); //within the convergence range? if (this_num <= 1.44466786100976613366 && this_num >= 0.06598803584531253708) { + var negln = Decimal.ln(this).neg(); + //For bases above 1, b^x = x has two solutions. The lower solution is a stable equilibrium, the upper solution is an unstable equilibrium. + var lower = negln.lambertw().div(negln); + // However, if the base is below 1, there's only the stable equilibrium solution. + if (this_num < 1) return lower; + var upper = negln.lambertw(false).div(negln); //hotfix for the very edge of the number range not being handled properly if (this_num > 1.444667861009099) { - return Decimal.fromNumber(Math.E); + lower = upper = Decimal.fromNumber(Math.E); } - //Formula for infinite height power tower. - var negln = Decimal.ln(this).neg(); - return negln.lambertw().div(negln); + payload = D(payload); + if (payload.eq(upper)) return upper;else if (payload.lt(upper)) return lower;else return FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); } else if (this_num > 1.44466786100976613366) { //explodes to infinity - // TODO: replace this with Decimal.dInf - return Decimal.fromNumber(Number.POSITIVE_INFINITY); + return FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); } else { //0.06598803584531253708 > this_num >= 0: never converges //this_num < 0: quickly becomes a complex number - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } } //0^^x oscillates if we define 0^0 == 1 (which in javascript land we do), since then 0^^1 is 0, 0^^2 is 1, 0^^3 is 0, etc. payload is ignored @@ -2191,14 +2249,15 @@ if (height < 0) { return Decimal.iteratedlog(payload, this, -height, linear); } - payload = D(payload); + payload = new Decimal(payload); var oldheight = height; height = Math.trunc(height); var fracheight = oldheight - height; - if (this.gt(Decimal.dZero) && this.lte(1.44466786100976613366) && (oldheight > 10000 || !linear)) { - //similar to 0^^n, flip-flops between two values, converging slowly (or if it's below 0.06598803584531253708, never. so once again, the fractional part at the end will be a linear approximation (TODO: again pending knowledge of how to approximate better, although tbh I think it should in reality just be NaN) - height = Math.min(10000, height); - for (var i = 0; i < height; ++i) { + if (this.gt(Decimal.dZero) && (this.lt(1) || this.lte(1.44466786100976613366) && payload.lte(Decimal.ln(this).neg().lambertw(false).div(Decimal.ln(this).neg()))) && (oldheight > 10000 || !linear)) { + //similar to 0^^n, flip-flops between two values, converging slowly (or if it's below 0.06598803584531253708, never). So once again, the fractional part at the beginning will be a linear approximation (TODO: again pending knowledge of how to approximate better, although tbh I think it should in reality just be NaN) + var limitheight = Math.min(10000, height); + if (payload.eq(Decimal.dOne)) payload = this.pow(fracheight);else if (this.lt(1)) payload = payload.pow(1 - fracheight).mul(this.pow(payload).pow(fracheight));else payload = payload.layeradd(fracheight, this); + for (var i = 0; i < limitheight; ++i) { var old_payload = payload; payload = this.pow(payload); //stop early if we converge @@ -2206,13 +2265,8 @@ return payload; } } - if (fracheight != 0 || oldheight > 10000) { - var next_payload = this.pow(payload); - if (oldheight <= 10000 || Math.ceil(oldheight) % 2 == 0) { - return payload.mul(1 - fracheight).add(next_payload.mul(fracheight)); - } else { - return payload.mul(fracheight).add(next_payload.mul(1 - fracheight)); - } + if (oldheight > 10000 && Math.ceil(oldheight) % 2 == 1) { + return this.pow(payload); } return payload; } @@ -2234,6 +2288,8 @@ } else { if (this.eq(10)) { payload = payload.layeradd10(fracheight, linear); + } else if (this.lt(1)) { + payload = payload.pow(1 - fracheight).mul(this.pow(payload).pow(fracheight)); } else { payload = payload.layeradd(fracheight, this, linear); } @@ -2317,6 +2373,7 @@ if (base.eq(10)) { result = result.layeradd10(-fraction, linear); } else { + //I have no clue what a fractional times on a base below 1 should even mean, so I'm not going to bother - just let it be NaN (TODO: come up with what the answer actually should be) result = result.layeradd(-fraction, base, linear); } } @@ -2375,28 +2432,34 @@ //special cases: //slog base 0 or lower is NaN if (base.lte(Decimal.dZero)) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //slog base 1 is NaN if (base.eq(Decimal.dOne)) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //need to handle these small, wobbling bases specially if (base.lt(Decimal.dOne)) { if (this.eq(Decimal.dOne)) { - return Decimal.dZero; + return FC_NN(0, 0, 0); } if (this.eq(Decimal.dZero)) { - return Decimal.dNegOne; + return FC_NN(-1, 0, 1); } //0 < this < 1: ambiguous (happens multiple times) //this < 0: impossible (as far as I can tell) //this > 1: partially complex (http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html base 0.25 for proof) - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //slog_n(0) is -1 if (this.mag < 0 || this.eq(Decimal.dZero)) { - return Decimal.dNegOne; + return FC_NN(-1, 0, 1); + } + if (base.lt(1.44466786100976613366)) { + var negln = Decimal.ln(base).neg(); + var infTower = negln.lambertw().div(negln); + if (this.eq(infTower)) return FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); + if (this.gt(infTower)) return FC_NN(Number.NaN, Number.NaN, Number.NaN); } var result = 0; var copy = Decimal.fromDecimal(this); @@ -2507,41 +2570,87 @@ key: "layeradd", value: function layeradd(diff, base) { var linear = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; - var slogthis = this.slog(base).toNumber(); + var baseD = D(base); + if (baseD.gt(1) && baseD.lte(1.44466786100976613366)) { + var excessSlog = Decimal.excess_slog(this, base, linear); + var _slogthis = excessSlog[0].toNumber(); + var range = excessSlog[1]; + var _slogdest = _slogthis + diff; + var negln = Decimal.ln(base).neg(); + var lower = negln.lambertw().div(negln); + var upper = negln.lambertw(false).div(negln); + var slogzero = Decimal.dOne; + if (range == 1) slogzero = lower.mul(upper).sqrt();else if (range == 2) slogzero = upper.mul(2); + var slogone = baseD.pow(slogzero); + var wholeheight = Math.floor(_slogdest); + var fracheight = _slogdest - wholeheight; + var towertop = slogzero.pow(1 - fracheight).mul(slogone.pow(fracheight)); + return Decimal.tetrate(baseD, wholeheight, towertop, linear); //wholediff is a whole number so this is safe even if it ends up calling iteratedlog + } + + var slogthis = this.slog(base, 100, linear).toNumber(); var slogdest = slogthis + diff; if (slogdest >= 0) { return Decimal.tetrate(base, slogdest, Decimal.dOne, linear); } else if (!Number.isFinite(slogdest)) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } else if (slogdest >= -1) { return Decimal.log(Decimal.tetrate(base, slogdest + 1, Decimal.dOne, linear), base); } else { return Decimal.log(Decimal.log(Decimal.tetrate(base, slogdest + 2, Decimal.dOne, linear), base), base); } } + //Apparently having something be private but not static breaks everything + /** + * A strange version of slog for bases between 1 and e^1/e which can handle values above base^^Infinity. + * Returns a pair of a Decimal and a number, with the number always being 0, 1, or 2. The number indicates what range we're in: + * 0 means we're below the lower solution of b^x = x, and so the normal slog is used. + * 1 means we're between the two solutions of b^x = x, with the geometric mean of the two solutions arbitrarily chosen to be the value with a slog of 0. + * 2 means we're above the upper solution of b^x = x, with (upper solution * 2) arbitrarily chosen to be the value with a slog of 0. + * + * The values returned by this function don't really have much mathematical meaning, but the difference between two values does. + * Therefore, this function is kept private, but it's used for layeradd on these small bases. + */ + }, { + key: "lambertw", + value: /** * The Lambert W function, also called the omega function or product logarithm, is the solution W(x) === x*e^x. * https://en.wikipedia.org/wiki/Lambert_W_function + * + * This is a multi-valued function in the complex plane, but only two branches matter for real numbers: the "principal branch" W0, and the "non-principal branch" W_-1. + * W_0 works for any number >= -1/e, but W_-1 only works for nonpositive numbers >= -1/e. + * The "principal" parameter, which is true by default, decides which branch we're looking for: W_0 is used if principal is true, W_-1 is used if principal is false. */ //Some special values, for testing: https://en.wikipedia.org/wiki/Lambert_W_function#Special_values - }, { - key: "lambertw", - value: function lambertw() { + function lambertw() { + var principal = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; if (this.lt(-0.3678794411710499)) { - throw Error("lambertw is unimplemented for results less than -1, sorry!"); - } else if (this.mag < 0) { - return Decimal.fromNumber(f_lambertw(this.toNumber())); - } else if (this.layer === 0) { - return Decimal.fromNumber(f_lambertw(this.sign * this.mag)); - } else if (this.layer === 1) { - return d_lambertw(this); - } else if (this.layer === 2) { - return d_lambertw(this); - } - if (this.layer >= 3) { - return FC_NN(this.sign, this.layer - 1, this.mag); + return FC_NN(Number.NaN, Number.NaN, Number.NaN); //complex + } else if (principal) { + if (this.abs().lt("1e-300")) return new Decimal(this);else if (this.mag < 0) { + return Decimal.fromNumber(f_lambertw(this.toNumber())); + } else if (this.layer === 0) { + return Decimal.fromNumber(f_lambertw(this.sign * this.mag)); + } else if (this.lt("eee15")) { + return d_lambertw(this); + } else { + // Numbers this large would sometimes fail to converge using d_lambertw, and at this size this.ln() is close enough + return this.ln(); + } + } else { + if (this.sign === 1) { + return FC_NN(Number.NaN, Number.NaN, Number.NaN); //complex + } + + if (this.layer === 0) { + return Decimal.fromNumber(f_lambertw(this.sign * this.mag, 1e-10, false)); + } else if (this.layer == 1) { + return d_lambertw(this, 1e-10, false); + } else { + return this.neg().recip().lambertw().neg(); + } } - throw "Unhandled behavior in lambertw()"; } /** * The super square-root function - what number, tetrated to height 2, equals 'this'? https://en.wikipedia.org/wiki/Tetration#Super-root @@ -2567,10 +2676,10 @@ return this; } if (this.eq(Decimal.dInf)) { - return Decimal.dInf; + return FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); } if (!this.isFinite()) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //Using linear approximation, x^^n = x^n if 0 < n < 1 if (degree > 0 && degree < 1) { @@ -2582,7 +2691,7 @@ } //Super roots with -1 <= degree < 0 have either no solution or infinitely many solutions, and tetration with height <= -2 returns NaN, so super roots of degree <= -2 don't work if (degree <= 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //Infinite degree super-root is x^(1/x) between 1/e <= x <= e, undefined otherwise if (degree == Number.POSITIVE_INFINITY) { @@ -2590,20 +2699,20 @@ if (this_num < Math.E && this_num > _EXPN1) { return this.pow(this.recip()); } else { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } } //Special case: any super-root of 1 is 1 if (this.eq(1)) { - return Decimal.dOne; + return FC_NN(1, 0, 1); } //TODO: base < 0 (It'll probably be NaN anyway) if (this.lt(0)) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //Treat all numbers of layer <= -2 as zero, because they effectively are if (this.lte("1ee-16")) { - if (degree % 2 == 1) return this;else return Decimal.dNaN; + if (degree % 2 == 1) return new Decimal(this);else return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //this > 1 if (this.gt(1)) { @@ -2795,7 +2904,7 @@ if (_lower.eq(FC(1, 10, 1))) _guess = _upper.mul(2);else _guess = _lower.add(_upper).div(2); if (Decimal.pow(10, _guess).recip().tetrate(degree, 1, true).gt(this)) _upper = _guess;else _lower = _guess; if (_guess.eq(_previous)) _loopGoing = false;else _previous = _guess; - if (_upper.gt("1e18")) return Decimal.dNaN; + if (_upper.gt("1e18")) return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //using guess.neq(minimum) led to imprecision errors, so here's a fixed version of that if (!_guess.eq_tolerance(minimum, 1e-15)) { @@ -2805,7 +2914,7 @@ //Check if the root is in the zero range. if (maximum.eq(FC(1, 10, 1))) { //There is no zero range, so the super root doesn't exist - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } _lower = FC(1, 10, 1); _upper = maximum; @@ -2816,7 +2925,7 @@ if (_lower.eq(FC(1, 10, 1))) _guess = _upper.mul(2);else _guess = _lower.add(_upper).div(2); if (Decimal.pow(10, _guess).recip().tetrate(degree, 1, true).gt(this)) _upper = _guess;else _lower = _guess; if (_guess.eq(_previous)) _loopGoing = false;else _previous = _guess; - if (_upper.gt("1e18")) return Decimal.dNaN; + if (_upper.gt("1e18")) return FC_NN(Number.NaN, Number.NaN, Number.NaN); } return _guess.pow10().recip(); } @@ -2839,7 +2948,7 @@ var height = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 2; var payload = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : FC_NN(1, 0, 1); var linear = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; - payload = D(payload); + payload = new Decimal(payload); var oldheight = height; height = Math.trunc(height); var fracheight = oldheight - height; @@ -2877,7 +2986,7 @@ key: "sin", value: function sin() { if (this.mag < 0) { - return this; + return new Decimal(this); } if (this.layer === 0) { return Decimal.fromNumber(Math.sin(this.sign * this.mag)); @@ -2891,7 +3000,7 @@ key: "cos", value: function cos() { if (this.mag < 0) { - return Decimal.dOne; + return FC_NN(1, 0, 1); } if (this.layer === 0) { return Decimal.fromNumber(Math.cos(this.sign * this.mag)); @@ -2905,7 +3014,7 @@ key: "tan", value: function tan() { if (this.mag < 0) { - return this; + return new Decimal(this); } if (this.layer === 0) { return Decimal.fromNumber(Math.tan(this.sign * this.mag)); @@ -2919,7 +3028,7 @@ key: "asin", value: function asin() { if (this.mag < 0) { - return this; + return new Decimal(this); } if (this.layer === 0) { return Decimal.fromNumber(Math.asin(this.sign * this.mag)); @@ -2947,7 +3056,7 @@ key: "atan", value: function atan() { if (this.mag < 0) { - return this; + return new Decimal(this); } if (this.layer === 0) { return Decimal.fromNumber(Math.atan(this.sign * this.mag)); @@ -3012,7 +3121,7 @@ key: "ascensionPenalty", value: function ascensionPenalty(ascensions) { if (ascensions === 0) { - return this; + return new Decimal(this); } return this.root(Decimal.pow(10, ascensions)); } @@ -3134,7 +3243,7 @@ // This should never happen... but some users like Prestige Tree Rewritten // pass undefined values in as DecimalSources, so we should handle this // case to not break them. - return Decimal.dZero; + return FC_NN(0, 0, 0); } } /** @@ -3897,11 +4006,15 @@ /** * The Lambert W function, also called the omega function or product logarithm, is the solution W(x) === x*e^x. * https://en.wikipedia.org/wiki/Lambert_W_function + * + * This is a multi-valued function in the complex plane, but only two branches matter for real numbers: the "principal branch" W0, and the "non-principal branch" W_-1. + * W_0 works for any number >= -1/e, but W_-1 only works for negative numbers >= -1/e. + * The "principal" parameter, which is true by default, decides which branch we're looking for: W_0 is used if principal is true, W_-1 is used if principal is false. */ }, { key: "lambertw", - value: function lambertw(value) { - return D(value).lambertw(); + value: function lambertw(value, principal) { + return D(value).lambertw(principal); } /** * The super square-root function - what number, tetrated to height 2, equals 'value'? https://en.wikipedia.org/wiki/Tetration#Super-root @@ -4210,6 +4323,109 @@ return Math.pow(base, Math.log(lower) / Math.log(base) * (1 - frac) + Math.log(upper) / Math.log(base) * frac); } } + }, { + key: "excess_slog", + value: function excess_slog(value, base) { + var linear = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + value = D(value); + base = D(base); + var baseD = base; + base = base.toNumber(); + if (base == 1 || base <= 0) return [FC_NN(Number.NaN, Number.NaN, Number.NaN), 0]; + if (base > 1.44466786100976613366) return [value.slog(base, 100, linear), 0]; + var negln = Decimal.ln(base).neg(); + var lower = negln.lambertw().div(negln); + var upper = Decimal.dInf; + if (base > 1) upper = negln.lambertw(false).div(negln); + if (base > 1.444667861009099) { + lower = upper = Decimal.fromNumber(Math.E); + } + if (value.lt(lower)) return [value.slog(base, 100, linear), 0]; + if (value.eq(lower)) return [FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY), 0]; + if (value.eq(upper)) return [FC_NN(1, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY), 2]; + if (value.gt(upper)) { + var slogzero = upper.mul(2); + var slogone = baseD.pow(slogzero); + var estimate = 0; + if (value.gte(slogzero) && value.lt(slogone)) estimate = 0;else if (value.gte(slogone)) { + var payload = slogone; + estimate = 1; + while (payload.lt(value)) { + payload = baseD.pow(payload); + estimate = estimate + 1; + if (payload.layer > 3) { + var layersleft = Math.floor(value.layer - payload.layer + 1); + payload = baseD.iteratedexp(layersleft, payload, linear); + estimate = estimate + layersleft; + } + } + if (payload.gt(value)) { + payload = payload.log(base); + estimate = estimate - 1; + } + } else if (value.lt(slogzero)) { + var _payload5 = slogzero; + estimate = 0; + while (_payload5.gt(value)) { + _payload5 = _payload5.log(base); + estimate = estimate - 1; + } + } + var fracheight = 0; + var tested = 0; + var step_size = 0.5; + var towertop = slogzero; + var guess = Decimal.dZero; + while (step_size > 1e-16) { + tested = fracheight + step_size; + towertop = slogzero.pow(1 - tested).mul(slogone.pow(tested)); //Weighted geometric average + guess = Decimal.iteratedexp(base, estimate, towertop); + if (guess.eq(value)) return [new Decimal(estimate + tested), 2];else if (guess.lt(value)) fracheight += step_size; + step_size /= 2; + } + if (guess.neq_tolerance(value, 1e-7)) return [FC_NN(Number.NaN, Number.NaN, Number.NaN), 0]; + return [new Decimal(estimate + fracheight), 2]; + } + if (value.lt(upper) && value.gt(lower)) { + var _slogzero = lower.mul(upper).sqrt(); //Geometric mean of the two b^x = x solutions + var _slogone = baseD.pow(_slogzero); + var _estimate = 0; + if (value.lte(_slogzero) && value.gt(_slogone)) _estimate = 0;else if (value.lte(_slogone)) { + var _payload6 = _slogone; + _estimate = 1; + while (_payload6.gt(value)) { + _payload6 = baseD.pow(_payload6); + _estimate = _estimate + 1; + } + if (_payload6.lt(value)) { + _payload6 = _payload6.log(base); + _estimate = _estimate - 1; + } + } else if (value.gt(_slogzero)) { + var _payload7 = _slogzero; + _estimate = 0; + while (_payload7.lt(value)) { + _payload7 = _payload7.log(base); + _estimate = _estimate - 1; + } + } + var _fracheight = 0; + var _tested = 0; + var _step_size = 0.5; + var _towertop = _slogzero; + var _guess2 = Decimal.dZero; + while (_step_size > 1e-16) { + _tested = _fracheight + _step_size; + _towertop = _slogzero.pow(1 - _tested).mul(_slogone.pow(_tested)); //Weighted geometric average + _guess2 = Decimal.iteratedexp(base, _estimate, _towertop); + if (_guess2.eq(value)) return [new Decimal(_estimate + _tested), 1];else if (_guess2.gt(value)) _fracheight += _step_size; + _step_size /= 2; + } + if (_guess2.neq_tolerance(value, 1e-7)) return [FC_NN(Number.NaN, Number.NaN, Number.NaN), 0]; + return [new Decimal(_estimate + _fracheight), 1]; + } + throw new Error("Unhandled behavior in excess_slog"); + } }]); return Decimal; }(); @@ -4220,7 +4436,7 @@ Decimal.dTen = FC_NN(1, 0, 10); Decimal.dNaN = FC_NN(Number.NaN, Number.NaN, Number.NaN); Decimal.dInf = FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); - Decimal.dNegInf = FC_NN(-1, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY); + Decimal.dNegInf = FC_NN(-1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); Decimal.dNumberMax = FC(1, 0, Number.MAX_VALUE); Decimal.dNumberMin = FC(1, 0, Number.MIN_VALUE); Decimal.fromStringCache = new LRUCache(DEFAULT_FROM_STRING_CACHE_SIZE); diff --git a/break_eternity.min.js b/break_eternity.min.js index 0c04d5f..135d3a0 100644 --- a/break_eternity.min.js +++ b/break_eternity.min.js @@ -1 +1 @@ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).Decimal=e()}(this,(function(){"use strict";function t(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function e(t,e){for(var i=0;ithis.maxSize;){var r=this.last;this.map.delete(r.key),this.last=r.prev,this.last.next=void 0}}}}]),e}(),n=i((function e(i,r){t(this,e),this.next=void 0,this.prev=void 0,this.key=i,this.value=r})),a=Math.log10(9e15),s=function(){for(var t=[],e=-323;e<=308;e++)t.push(Number("1e"+e));return function(e){return t[e+323]}}(),u=[2,Math.E,3,4,5,6,7,8,9,10],o=[[1,1.0891180521811203,1.1789767925673957,1.2701455431742086,1.3632090180450092,1.4587818160364217,1.5575237916251419,1.6601571006859253,1.767485818836978,1.8804192098842727,2],[1,1.1121114330934079,1.231038924931609,1.3583836963111375,1.4960519303993531,1.6463542337511945,1.8121385357018724,1.996971324618307,2.2053895545527546,2.4432574483385254,Math.E],[1,1.1187738849693603,1.2464963939368214,1.38527004705667,1.5376664685821402,1.7068895236551784,1.897001227148399,2.1132403089001035,2.362480153784171,2.6539010333870774,3],[1,1.1367350847096405,1.2889510672956703,1.4606478703324786,1.6570295196661111,1.8850062585672889,2.1539465047453485,2.476829779693097,2.872061932789197,3.3664204535587183,4],[1,1.1494592900767588,1.319708228183931,1.5166291280087583,1.748171114438024,2.0253263297298045,2.3636668498288547,2.7858359149579424,3.3257226212448145,4.035730287722532,5],[1,1.159225940787673,1.343712473580932,1.5611293155111927,1.8221199554561318,2.14183924486326,2.542468319282638,3.0574682501653316,3.7390572020926873,4.6719550537360774,6],[1,1.1670905356972596,1.3632807444991446,1.5979222279405536,1.8842640123816674,2.2416069644878687,2.69893426559423,3.3012632110403577,4.121250340630164,5.281493033448316,7],[1,1.1736630594087796,1.379783782386201,1.6292821855668218,1.9378971836180754,2.3289975651071977,2.8384347394720835,3.5232708454565906,4.478242031114584,5.868592169644505,8],[1,1.1793017514670474,1.394054150657457,1.65664127441059,1.985170999970283,2.4069682290577457,2.9647310119960752,3.7278665320924946,4.814462547283592,6.436522247411611,9],[1,1.1840100246247336,1.4061375836156955,1.6802272208863964,2.026757028388619,2.4770056063449646,3.080525271755482,3.9191964192627284,5.135152840833187,6.989961179534715,10]],h=[[-1,-.9194161097107025,-.8335625019330468,-.7425599821143978,-.6466611521029437,-.5462617907227869,-.4419033816638769,-.3342645487554494,-.224140440909962,-.11241087890006762,0],[-1,-.90603157029014,-.80786507256596,-.7064666939634,-.60294836853664,-.49849837513117,-.39430303318768,-.29147201034755,-.19097820800866,-.09361896280296,0],[-1,-.9021579584316141,-.8005762598234203,-.6964780623319391,-.5911906810998454,-.486050182576545,-.3823089430815083,-.28106046722897615,-.1831906535795894,-.08935809204418144,0],[-1,-.8917227442365535,-.781258746326964,-.6705130326902455,-.5612813129406509,-.4551067709033134,-.35319256652135966,-.2563741554088552,-.1651412821106526,-.0796919581982668,0],[-1,-.8843387974366064,-.7678744063886243,-.6529563724510552,-.5415870994657841,-.4352842206588936,-.33504449124791424,-.24138853420685147,-.15445285440944467,-.07409659641336663,0],[-1,-.8786709358426346,-.7577735191184886,-.6399546189952064,-.527284921869926,-.4211627631006314,-.3223479611761232,-.23107655627789858,-.1472057700818259,-.07035171210706326,0],[-1,-.8740862815291583,-.7497032990976209,-.6297119746181752,-.5161838335958787,-.41036238255751956,-.31277212146489963,-.2233976621705518,-.1418697367979619,-.06762117662323441,0],[-1,-.8702632331800649,-.7430366914122081,-.6213373075161548,-.5072025698095242,-.40171437727184167,-.30517930701410456,-.21736343968190863,-.137710238299109,-.06550774483471955,0],[-1,-.8670016295947213,-.7373984232432306,-.6143173985094293,-.49973884395492807,-.394584953527678,-.2989649949848695,-.21245647317021688,-.13434688362382652,-.0638072667348083,0],[-1,-.8641642839543857,-.732534623168535,-.6083127477059322,-.4934049257184696,-.3885773075899922,-.29376029055315767,-.2083678561173622,-.13155653399373268,-.062401588652553186,0]],l=function(t){return N.fromValue_noAlloc(t)},m=function(t,e,i){return N.fromComponents(t,e,i)},g=function(t,e,i){return N.fromComponents_noNormalize(t,e,i)},f=function(t,e){var i=e+1,r=Math.ceil(Math.log10(Math.abs(t))),n=Math.round(t*Math.pow(10,i-r))*Math.pow(10,r-i);return parseFloat(n.toFixed(Math.max(i-r,0)))},c=function(t){return Math.sign(t)*Math.log10(Math.abs(t))},y=.5671432904097838,v=function(t){var e,i,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1e-10;if(!Number.isFinite(t))return t;if(0===t)return t;if(1===t)return y;e=t<10?0:Math.log(t)-Math.log(Math.log(t));for(var n=0;n<100;++n){if(i=(t*Math.exp(-e)+e*e)/(e+1),Math.abs(i-e)1&&void 0!==arguments[1]?arguments[1]:1e-10;if(!Number.isFinite(t.mag))return t;if(t.eq(N.dZero))return t;if(t.eq(N.dOne))return N.fromNumber(y);e=N.ln(t);for(var s=0;s<100;++s){if(i=e.neg().exp(),r=e.sub(t.mul(i)),n=e.sub(r.div(e.add(1).sub(e.add(2).mul(r).div(N.mul(2,e).add(2))))),N.abs(n.sub(e)).lt(N.abs(n).mul(a)))return n;e=n}throw Error("Iteration failed to converge: ".concat(t.toString()))}var N=function(){function e(i){t(this,e),this.sign=0,this.mag=0,this.layer=0,i instanceof e?this.fromDecimal(i):"number"==typeof i?this.fromNumber(i):"string"==typeof i&&this.fromString(i)}return i(e,[{key:"m",get:function(){if(0===this.sign)return 0;if(0===this.layer){var t,e=Math.floor(Math.log10(this.mag));return t=5e-324===this.mag?5:this.mag/s(e),this.sign*t}if(1===this.layer){var i=this.mag-Math.floor(this.mag);return this.sign*Math.pow(10,i)}return this.sign},set:function(t){this.layer<=2?this.fromMantissaExponent(t,this.e):(this.sign=Math.sign(t),0===this.sign&&(this.layer=0,this.exponent=0))}},{key:"e",get:function(){return 0===this.sign?0:0===this.layer?Math.floor(Math.log10(this.mag)):1===this.layer?Math.floor(this.mag):2===this.layer?Math.floor(Math.sign(this.mag)*Math.pow(10,Math.abs(this.mag))):this.mag*Number.POSITIVE_INFINITY},set:function(t){this.fromMantissaExponent(this.m,t)}},{key:"s",get:function(){return this.sign},set:function(t){0===t?(this.sign=0,this.layer=0,this.mag=0):this.sign=t}},{key:"mantissa",get:function(){return this.m},set:function(t){this.m=t}},{key:"exponent",get:function(){return this.e},set:function(t){this.e=t}},{key:"normalize",value:function(){if(0===this.sign||0===this.mag&&0===this.layer||this.mag===Number.NEGATIVE_INFINITY&&this.layer>0&&Number.isFinite(this.layer))return this.sign=0,this.mag=0,this.layer=0,this;if(0===this.layer&&this.mag<0&&(this.mag=-this.mag,this.sign=-this.sign),this.mag===Number.POSITIVE_INFINITY||this.layer===Number.POSITIVE_INFINITY||this.mag===Number.NEGATIVE_INFINITY||this.layer===Number.NEGATIVE_INFINITY)return 1==this.sign?(this.mag=Number.POSITIVE_INFINITY,this.layer=Number.POSITIVE_INFINITY):-1==this.sign&&(this.mag=Number.NEGATIVE_INFINITY,this.layer=Number.NEGATIVE_INFINITY),this;if(0===this.layer&&this.mag<1/9e15)return this.layer+=1,this.mag=Math.log10(this.mag),this;var t=Math.abs(this.mag),e=Math.sign(this.mag);if(t>=9e15)return this.layer+=1,this.mag=e*Math.log10(t),this;for(;t0;)this.layer-=1,0===this.layer?this.mag=Math.pow(10,this.mag):(this.mag=e*Math.pow(10,t),t=Math.abs(this.mag),e=Math.sign(this.mag));return 0===this.layer&&(this.mag<0?(this.mag=-this.mag,this.sign=-this.sign):0===this.mag&&(this.sign=0)),(Number.isNaN(this.sign)||Number.isNaN(this.layer)||Number.isNaN(this.mag))&&(this.sign=Number.NaN,this.layer=Number.NaN,this.mag=Number.NaN),this}},{key:"fromComponents",value:function(t,e,i){return this.sign=t,this.layer=e,this.mag=i,this.normalize(),this}},{key:"fromComponents_noNormalize",value:function(t,e,i){return this.sign=t,this.layer=e,this.mag=i,this}},{key:"fromMantissaExponent",value:function(t,e){return this.layer=1,this.sign=Math.sign(t),t=Math.abs(t),this.mag=e+Math.log10(t),this.normalize(),this}},{key:"fromMantissaExponent_noNormalize",value:function(t,e){return this.fromMantissaExponent(t,e),this}},{key:"fromDecimal",value:function(t){return this.sign=t.sign,this.layer=t.layer,this.mag=t.mag,this}},{key:"fromNumber",value:function(t){return this.mag=Math.abs(t),this.sign=Math.sign(t),this.layer=0,this.normalize(),this}},{key:"fromString",value:function(t){var i=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=t,n=e.fromStringCache.get(r);if(void 0!==n)return this.fromDecimal(n);var a=(t=t.replace(",","")).split("^^^");if(2===a.length){var s=parseFloat(a[0]),u=parseFloat(a[1]),o=a[1].split(";"),h=1;if(2===o.length&&(h=parseFloat(o[1]),isFinite(h)||(h=1)),isFinite(s)&&isFinite(u)){var g=e.pentate(s,u,h,i);return this.sign=g.sign,this.layer=g.layer,this.mag=g.mag,e.fromStringCache.maxSize>=1&&e.fromStringCache.set(r,e.fromDecimal(this)),this}}var f=t.split("^^");if(2===f.length){var y=parseFloat(f[0]),v=parseFloat(f[1]),d=f[1].split(";"),N=1;if(2===d.length&&(N=parseFloat(d[1]),isFinite(N)||(N=1)),isFinite(y)&&isFinite(v)){var p=e.tetrate(y,v,N,i);return this.sign=p.sign,this.layer=p.layer,this.mag=p.mag,e.fromStringCache.maxSize>=1&&e.fromStringCache.set(r,e.fromDecimal(this)),this}}var b,k,M=t.split("^");if(2===M.length){var I=parseFloat(M[0]),_=parseFloat(M[1]);if(isFinite(I)&&isFinite(_)){var F=e.pow(I,_);return this.sign=F.sign,this.layer=F.layer,this.mag=F.mag,e.fromStringCache.maxSize>=1&&e.fromStringCache.set(r,e.fromDecimal(this)),this}}var w=(t=t.trim().toLowerCase()).split("pt");if(2===w.length){b=10,k=parseFloat(w[0]),w[1]=w[1].replace("(",""),w[1]=w[1].replace(")","");var S=parseFloat(w[1]);if(isFinite(S)||(S=1),isFinite(b)&&isFinite(k)){var q=e.tetrate(b,k,S,i);return this.sign=q.sign,this.layer=q.layer,this.mag=q.mag,e.fromStringCache.maxSize>=1&&e.fromStringCache.set(r,e.fromDecimal(this)),this}}if(2===(w=t.split("p")).length){b=10,k=parseFloat(w[0]),w[1]=w[1].replace("(",""),w[1]=w[1].replace(")","");var x=parseFloat(w[1]);if(isFinite(x)||(x=1),isFinite(b)&&isFinite(k)){var E=e.tetrate(b,k,x,i);return this.sign=E.sign,this.layer=E.layer,this.mag=E.mag,e.fromStringCache.maxSize>=1&&e.fromStringCache.set(r,e.fromDecimal(this)),this}}if(2===(w=t.split("f")).length){b=10,w[0]=w[0].replace("(",""),w[0]=w[0].replace(")","");var T=parseFloat(w[0]);if(w[1]=w[1].replace("(",""),w[1]=w[1].replace(")",""),k=parseFloat(w[1]),isFinite(T)||(T=1),isFinite(b)&&isFinite(k)){var O=e.tetrate(b,k,T,i);return this.sign=O.sign,this.layer=O.layer,this.mag=O.mag,e.fromStringCache.maxSize>=1&&e.fromStringCache.set(r,e.fromDecimal(this)),this}}var C=t.split("e"),z=C.length-1;if(0===z){var V=parseFloat(t);if(isFinite(V))return this.fromNumber(V),e.fromStringCache.size>=1&&e.fromStringCache.set(r,e.fromDecimal(this)),this}else if(1===z){var A=parseFloat(t);if(isFinite(A)&&0!==A)return this.fromNumber(A),e.fromStringCache.maxSize>=1&&e.fromStringCache.set(r,e.fromDecimal(this)),this}var P=t.split("e^");if(2===P.length){this.sign=1,"-"==P[0].charAt(0)&&(this.sign=-1);for(var Y="",D=0;D=43&&Z<=57||101===Z))return this.layer=parseFloat(Y),this.mag=parseFloat(P[1].substr(D+1)),this.normalize(),e.fromStringCache.maxSize>=1&&e.fromStringCache.set(r,e.fromDecimal(this)),this;Y+=P[1].charAt(D)}}if(z<1)return this.sign=0,this.layer=0,this.mag=0,e.fromStringCache.maxSize>=1&&e.fromStringCache.set(r,e.fromDecimal(this)),this;var G=parseFloat(C[0]);if(0===G)return this.sign=0,this.layer=0,this.mag=0,e.fromStringCache.maxSize>=1&&e.fromStringCache.set(r,e.fromDecimal(this)),this;var L=parseFloat(C[C.length-1]);if(z>=2){var j=parseFloat(C[C.length-2]);isFinite(j)&&(L*=Math.sign(j),L+=c(j))}if(isFinite(G))if(1===z)this.sign=Math.sign(G),this.layer=1,this.mag=L+Math.log10(Math.abs(G));else{if(this.sign=Math.sign(G),this.layer=z,2===z){var W=e.mul(m(1,2,L),l(G));return this.sign=W.sign,this.layer=W.layer,this.mag=W.mag,e.fromStringCache.maxSize>=1&&e.fromStringCache.set(r,e.fromDecimal(this)),this}this.mag=L}else this.sign="-"===C[0]?-1:1,this.layer=z,this.mag=L;return this.normalize(),e.fromStringCache.maxSize>=1&&e.fromStringCache.set(r,e.fromDecimal(this)),this}},{key:"fromValue",value:function(t){return t instanceof e?this.fromDecimal(t):"number"==typeof t?this.fromNumber(t):"string"==typeof t?this.fromString(t):(this.sign=0,this.layer=0,this.mag=0,this)}},{key:"toNumber",value:function(){return this.mag===Number.POSITIVE_INFINITY&&this.layer===Number.POSITIVE_INFINITY&&1===this.sign?Number.POSITIVE_INFINITY:this.mag===Number.NEGATIVE_INFINITY&&this.layer===Number.NEGATIVE_INFINITY&&-1===this.sign?Number.NEGATIVE_INFINITY:Number.isFinite(this.layer)?0===this.layer?this.sign*this.mag:1===this.layer?this.sign*Math.pow(10,this.mag):this.mag>0?this.sign>0?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:0:Number.NaN}},{key:"mantissaWithDecimalPlaces",value:function(t){return isNaN(this.m)?Number.NaN:0===this.m?0:f(this.m,t)}},{key:"magnitudeWithDecimalPlaces",value:function(t){return isNaN(this.mag)?Number.NaN:0===this.mag?0:f(this.mag,t)}},{key:"toString",value:function(){return isNaN(this.layer)||isNaN(this.sign)||isNaN(this.mag)?"NaN":this.mag===Number.POSITIVE_INFINITY||this.layer===Number.POSITIVE_INFINITY||this.mag===Number.NEGATIVE_INFINITY||this.layer===Number.NEGATIVE_INFINITY?1===this.sign?"Infinity":"-Infinity":0===this.layer?this.mag<1e21&&this.mag>1e-7||0===this.mag?(this.sign*this.mag).toString():this.m+"e"+this.e:1===this.layer?this.m+"e"+this.e:this.layer<=5?(-1===this.sign?"-":"")+"e".repeat(this.layer)+this.mag:(-1===this.sign?"-":"")+"(e^"+this.layer+")"+this.mag}},{key:"toExponential",value:function(t){return 0===this.layer?(this.sign*this.mag).toExponential(t):this.toStringWithDecimalPlaces(t)}},{key:"toFixed",value:function(t){return 0===this.layer?(this.sign*this.mag).toFixed(t):this.toStringWithDecimalPlaces(t)}},{key:"toPrecision",value:function(t){return this.e<=-7?this.toExponential(t-1):t>this.e?this.toFixed(t-this.exponent-1):this.toExponential(t-1)}},{key:"valueOf",value:function(){return this.toString()}},{key:"toJSON",value:function(){return this.toString()}},{key:"toStringWithDecimalPlaces",value:function(t){return 0===this.layer?this.mag<1e21&&this.mag>1e-7||0===this.mag?(this.sign*this.mag).toFixed(t):f(this.m,t)+"e"+f(this.e,t):1===this.layer?f(this.m,t)+"e"+f(this.e,t):this.layer<=5?(-1===this.sign?"-":"")+"e".repeat(this.layer)+f(this.mag,t):(-1===this.sign?"-":"")+"(e^"+this.layer+")"+f(this.mag,t)}},{key:"abs",value:function(){return g(0===this.sign?0:1,this.layer,this.mag)}},{key:"neg",value:function(){return g(-this.sign,this.layer,this.mag)}},{key:"negate",value:function(){return this.neg()}},{key:"negated",value:function(){return this.neg()}},{key:"sgn",value:function(){return this.sign}},{key:"round",value:function(){return this.mag<0?e.dZero:0===this.layer?m(this.sign,0,Math.round(this.mag)):this}},{key:"floor",value:function(){return this.mag<0?-1===this.sign?e.dNegOne:e.dZero:-1===this.sign?this.neg().ceil().neg():0===this.layer?m(this.sign,0,Math.floor(this.mag)):this}},{key:"ceil",value:function(){return this.mag<0?1===this.sign?e.dOne:e.dZero:-1===this.sign?this.neg().floor().neg():0===this.layer?m(this.sign,0,Math.ceil(this.mag)):this}},{key:"trunc",value:function(){return this.mag<0?e.dZero:0===this.layer?m(this.sign,0,Math.trunc(this.mag)):this}},{key:"add",value:function(t){var i,r,n=l(t);if(!Number.isFinite(this.layer))return this;if(!Number.isFinite(n.layer))return n;if(0===this.sign)return n;if(0===n.sign)return this;if(this.sign===-n.sign&&this.layer===n.layer&&this.mag===n.mag)return g(0,0,0);if(this.layer>=2||n.layer>=2)return this.maxabs(n);if(e.cmpabs(this,n)>0?(i=this,r=n):(i=n,r=this),0===i.layer&&0===r.layer)return e.fromNumber(i.sign*i.mag+r.sign*r.mag);var a=i.layer*Math.sign(i.mag),s=r.layer*Math.sign(r.mag);if(a-s>=2)return i;if(0===a&&-1===s){if(Math.abs(r.mag-Math.log10(i.mag))>17)return i;var u=Math.pow(10,Math.log10(i.mag)-r.mag),o=r.sign+i.sign*u;return m(Math.sign(o),1,r.mag+Math.log10(Math.abs(o)))}if(1===a&&0===s){if(Math.abs(i.mag-Math.log10(r.mag))>17)return i;var h=Math.pow(10,i.mag-Math.log10(r.mag)),f=r.sign+i.sign*h;return m(Math.sign(f),1,Math.log10(r.mag)+Math.log10(Math.abs(f)))}if(Math.abs(i.mag-r.mag)>17)return i;var c=Math.pow(10,i.mag-r.mag),y=r.sign+i.sign*c;return m(Math.sign(y),1,r.mag+Math.log10(Math.abs(y)))}},{key:"plus",value:function(t){return this.add(t)}},{key:"sub",value:function(t){return this.add(l(t).neg())}},{key:"subtract",value:function(t){return this.sub(t)}},{key:"minus",value:function(t){return this.sub(t)}},{key:"mul",value:function(t){var i,r,n=l(t);if(!Number.isFinite(this.layer))return this;if(!Number.isFinite(n.layer))return n;if(0===this.sign||0===n.sign)return g(0,0,0);if(this.layer===n.layer&&this.mag===-n.mag)return g(this.sign*n.sign,0,1);if(this.layer>n.layer||this.layer==n.layer&&Math.abs(this.mag)>Math.abs(n.mag)?(i=this,r=n):(i=n,r=this),0===i.layer&&0===r.layer)return e.fromNumber(i.sign*r.sign*i.mag*r.mag);if(i.layer>=3||i.layer-r.layer>=2)return m(i.sign*r.sign,i.layer,i.mag);if(1===i.layer&&0===r.layer)return m(i.sign*r.sign,1,i.mag+Math.log10(r.mag));if(1===i.layer&&1===r.layer)return m(i.sign*r.sign,1,i.mag+r.mag);if(2===i.layer&&1===r.layer){var a=m(Math.sign(i.mag),i.layer-1,Math.abs(i.mag)).add(m(Math.sign(r.mag),r.layer-1,Math.abs(r.mag)));return m(i.sign*r.sign,a.layer+1,a.sign*a.mag)}if(2===i.layer&&2===r.layer){var s=m(Math.sign(i.mag),i.layer-1,Math.abs(i.mag)).add(m(Math.sign(r.mag),r.layer-1,Math.abs(r.mag)));return m(i.sign*r.sign,s.layer+1,s.sign*s.mag)}throw Error("Bad arguments to mul: "+this+", "+t)}},{key:"multiply",value:function(t){return this.mul(t)}},{key:"times",value:function(t){return this.mul(t)}},{key:"div",value:function(t){var e=l(t);return this.mul(e.recip())}},{key:"divide",value:function(t){return this.div(t)}},{key:"divideBy",value:function(t){return this.div(t)}},{key:"dividedBy",value:function(t){return this.div(t)}},{key:"recip",value:function(){return 0===this.mag?e.dNaN:0===this.layer?m(this.sign,0,1/this.mag):m(this.sign,this.layer,-this.mag)}},{key:"reciprocal",value:function(){return this.recip()}},{key:"reciprocate",value:function(){return this.recip()}},{key:"mod",value:function(t){var i=l(t).abs();if(i.eq(e.dZero))return e.dZero;var r=this.toNumber(),n=i.toNumber();return isFinite(r)&&isFinite(n)&&0!=r&&0!=n?new e(r%n):this.sub(i).eq(this)?e.dZero:i.sub(this).eq(i)?this:-1==this.sign?this.abs().mod(i).neg():this.sub(this.div(i).floor().mul(i))}},{key:"modulo",value:function(t){return this.mod(t)}},{key:"modular",value:function(t){return this.mod(t)}},{key:"cmp",value:function(t){var e=l(t);return this.sign>e.sign?1:this.sign0?this.layer:-this.layer,r=e.mag>0?e.layer:-e.layer;return i>r?1:ie.mag?1:this.mag0?e:this}},{key:"clamp",value:function(t,e){return this.max(t).min(e)}},{key:"clampMin",value:function(t){return this.max(t)}},{key:"clampMax",value:function(t){return this.min(t)}},{key:"cmp_tolerance",value:function(t,e){var i=l(t);return this.eq_tolerance(i,e)?0:this.cmp(i)}},{key:"compare_tolerance",value:function(t,e){return this.cmp_tolerance(t,e)}},{key:"eq_tolerance",value:function(t,e){var i=l(t);if(null==e&&(e=1e-7),this.sign!==i.sign)return!1;if(Math.abs(this.layer-i.layer)>1)return!1;var r=this.mag,n=i.mag;return this.layer>i.layer&&(n=c(n)),this.layer0?m(Math.sign(this.mag),this.layer-1,Math.abs(this.mag)):m(1,0,Math.log10(this.mag))}},{key:"log10",value:function(){return this.sign<=0?e.dNaN:this.layer>0?m(Math.sign(this.mag),this.layer-1,Math.abs(this.mag)):m(this.sign,0,Math.log10(this.mag))}},{key:"log",value:function(t){return t=l(t),this.sign<=0||t.sign<=0||1===t.sign&&0===t.layer&&1===t.mag?e.dNaN:0===this.layer&&0===t.layer?m(this.sign,0,Math.log(this.mag)/Math.log(t.mag)):e.div(this.log10(),t.log10())}},{key:"log2",value:function(){return this.sign<=0?e.dNaN:0===this.layer?m(this.sign,0,Math.log2(this.mag)):1===this.layer?m(Math.sign(this.mag),0,3.321928094887362*Math.abs(this.mag)):2===this.layer?m(Math.sign(this.mag),1,Math.abs(this.mag)+.5213902276543247):m(Math.sign(this.mag),this.layer-1,Math.abs(this.mag))}},{key:"ln",value:function(){return this.sign<=0?e.dNaN:0===this.layer?m(this.sign,0,Math.log(this.mag)):1===this.layer?m(Math.sign(this.mag),0,2.302585092994046*Math.abs(this.mag)):2===this.layer?m(Math.sign(this.mag),1,Math.abs(this.mag)+.36221568869946325):m(Math.sign(this.mag),this.layer-1,Math.abs(this.mag))}},{key:"logarithm",value:function(t){return this.log(t)}},{key:"pow",value:function(t){var i=this,r=l(t);if(0===i.sign)return r.eq(0)?g(1,0,1):i;if(1===i.sign&&0===i.layer&&1===i.mag)return i;if(0===r.sign)return g(1,0,1);if(1===r.sign&&0===r.layer&&1===r.mag)return i;var n=i.absLog10().mul(r).pow10();return-1===this.sign?Math.abs(r.toNumber()%2)%2==1?n.neg():Math.abs(r.toNumber()%2)%2==0?n:e.dNaN:n}},{key:"pow10",value:function(){if(!Number.isFinite(this.layer)||!Number.isFinite(this.mag))return e.dNaN;var t=this;if(0===t.layer){var i=Math.pow(10,t.sign*t.mag);if(Number.isFinite(i)&&Math.abs(i)>=.1)return m(1,0,i);if(0===t.sign)return e.dOne;t=g(t.sign,t.layer+1,Math.log10(t.mag))}return t.sign>0&&t.mag>=0?m(t.sign,t.layer+1,t.mag):t.sign<0&&t.mag>=0?m(-t.sign,t.layer+1,-t.mag):e.dOne}},{key:"pow_base",value:function(t){return l(t).pow(this)}},{key:"root",value:function(t){var e=l(t);return this.pow(e.recip())}},{key:"factorial",value:function(){return this.mag<0||0===this.layer?this.add(1).gamma():1===this.layer?e.exp(e.mul(this,e.ln(this).sub(1))):e.exp(this)}},{key:"gamma",value:function(){if(this.mag<0)return this.recip();if(0===this.layer){if(this.lt(g(1,0,24)))return e.fromNumber(function(t){if(!isFinite(t))return t;if(t<-50)return t===Math.trunc(t)?Number.NEGATIVE_INFINITY:0;for(var e=1;t<10;)e*=t,++t;var i=.9189385332046727;i+=((t-=1)+.5)*Math.log(t),i-=t;var r=t*t,n=t;return i+=1/(12*n),i+=1/(360*(n*=r)),i+=1/(1260*(n*=r)),i+=1/(1680*(n*=r)),i+=1/(1188*(n*=r)),i+=691/(360360*(n*=r)),i+=7/(1092*(n*=r)),i+=3617/(122400*(n*=r)),Math.exp(i)/e}(this.sign*this.mag));var t=this.mag-1,i=.9189385332046727;i+=(t+.5)*Math.log(t);var r=t*t,n=t,a=12*n,s=1/a,u=(i-=t)+s;if(u===i)return e.exp(i);if((u=(i=u)-(s=1/(a=360*(n*=r))))===i)return e.exp(i);i=u;var o=1/(a=1260*(n*=r));return i+=o,i-=o=1/(a=1680*(n*=r)),e.exp(i)}return 1===this.layer?e.exp(e.mul(this,e.ln(this).sub(1))):e.exp(this)}},{key:"lngamma",value:function(){return this.gamma().ln()}},{key:"exp",value:function(){return this.mag<0?e.dOne:0===this.layer&&this.mag<=709.7?e.fromNumber(Math.exp(this.sign*this.mag)):0===this.layer?m(1,1,this.sign*Math.log10(Math.E)*this.mag):1===this.layer?m(1,2,this.sign*(Math.log10(.4342944819032518)+this.mag)):m(1,this.layer+1,this.sign*this.mag)}},{key:"sqr",value:function(){return this.pow(2)}},{key:"sqrt",value:function(){if(0===this.layer)return e.fromNumber(Math.sqrt(this.sign*this.mag));if(1===this.layer)return m(1,2,Math.log10(this.mag)-.3010299956639812);var t=e.div(g(this.sign,this.layer-1,this.mag),g(1,0,2));return t.layer+=1,t.normalize(),t}},{key:"cube",value:function(){return this.pow(3)}},{key:"cbrt",value:function(){return this.pow(1/3)}},{key:"tetrate",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:2,i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:g(1,0,1),r=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(1===t)return e.pow(this,i);if(0===t)return new e(i);if(this.eq(e.dOne))return e.dOne;if(this.eq(-1))return e.pow(this,i);if(t===Number.POSITIVE_INFINITY){var n=this.toNumber();if(n<=1.444667861009766&&n>=.06598803584531254){if(n>1.444667861009099)return e.fromNumber(Math.E);var a=e.ln(this).neg();return a.lambertw().div(a)}return n>1.444667861009766?e.fromNumber(Number.POSITIVE_INFINITY):e.dNaN}if(this.eq(e.dZero)){var s=Math.abs((t+1)%2);return s>1&&(s=2-s),e.fromNumber(s)}if(t<0)return e.iteratedlog(i,this,-t,r);i=l(i);var u=t,o=u-(t=Math.trunc(t));if(this.gt(e.dZero)&&this.lte(1.444667861009766)&&(u>1e4||!r)){t=Math.min(1e4,t);for(var h=0;h1e4){var f=this.pow(i);return u<=1e4||Math.ceil(u)%2==0?i.mul(1-o).add(f.mul(o)):i.mul(o).add(f.mul(1-o))}return i}0!==o&&(i.eq(e.dOne)?this.gt(10)||r?i=this.pow(o):(i=e.fromNumber(e.tetrate_critical(this.toNumber(),o)),this.lt(2)&&(i=i.sub(1).mul(this.minus(1)).plus(1))):i=this.eq(10)?i.layeradd10(o,r):i.layeradd(o,this,r));for(var c=0;c3)return g(i.sign,i.layer+(t-c-1),i.mag);if(c>1e4)return i}return i}},{key:"iteratedexp",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:2,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:g(1,0,1),i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return this.tetrate(t,e,i)}},{key:"iteratedlog",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:10,i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1,r=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(i<0)return e.tetrate(t,-i,this,r);t=l(t);var n=e.fromDecimal(this),a=i,s=a-(i=Math.trunc(i));if(n.layer-t.layer>3){var u=Math.min(i,n.layer-t.layer-3);i-=u,n.layer-=u}for(var o=0;o1e4)return n}return s>0&&s<1&&(n=t.eq(10)?n.layeradd10(-s,r):n.layeradd(-s,t,r)),n}},{key:"slog",value:function(){for(var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:10,i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:100,r=arguments.length>2&&void 0!==arguments[2]&&arguments[2],n=.001,a=!1,s=!1,u=this.slog_internal(t,r).toNumber(),o=1;o1&&s!=l&&(a=!0),s=l,a?n/=2:n*=2,u+=n=Math.abs(n)*(l?-1:1),0===n)break}return e.fromNumber(u)}},{key:"slog_internal",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:10,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if((t=l(t)).lte(e.dZero))return e.dNaN;if(t.eq(e.dOne))return e.dNaN;if(t.lt(e.dOne))return this.eq(e.dOne)?e.dZero:this.eq(e.dZero)?e.dNegOne:e.dNaN;if(this.mag<0||this.eq(e.dZero))return e.dNegOne;var r=0,n=e.fromDecimal(this);if(n.layer-t.layer>3){var a=n.layer-t.layer-3;r+=a,n.layer-=a}for(var s=0;s<100;++s)if(n.lt(e.dZero))n=e.pow(t,n),r-=1;else{if(n.lte(e.dOne))return i?e.fromNumber(r+n.toNumber()-1):e.fromNumber(r+e.slog_critical(t.toNumber(),n.toNumber()));r+=1,n=e.log(n,t)}return e.fromNumber(r)}},{key:"layeradd10",value:function(t){var i=arguments.length>1&&void 0!==arguments[1]&&arguments[1];t=e.fromValue_noAlloc(t).toNumber();var r=e.fromDecimal(this);if(t>=1){r.mag<0&&r.layer>0?(r.sign=0,r.mag=0,r.layer=0):-1===r.sign&&0==r.layer&&(r.sign=1,r.mag=-r.mag);var n=Math.trunc(t);t-=n,r.layer+=n}if(t<=-1){var a=Math.trunc(t);if(t-=a,r.layer+=a,r.layer<0)for(var s=0;s<100;++s){if(r.layer++,r.mag=Math.log10(r.mag),!isFinite(r.mag))return 0===r.sign&&(r.sign=1),r.layer<0&&(r.layer=0),r.normalize();if(r.layer>=0)break}}for(;r.layer<0;)r.layer++,r.mag=Math.log10(r.mag);return 0===r.sign&&(r.sign=1,0===r.mag&&r.layer>=1&&(r.layer-=1,r.mag=1)),r.normalize(),0!==t?r.layeradd(t,10,i):r}},{key:"layeradd",value:function(t,i){var r=arguments.length>2&&void 0!==arguments[2]&&arguments[2],n=this.slog(i).toNumber(),a=n+t;return a>=0?e.tetrate(i,a,e.dOne,r):Number.isFinite(a)?a>=-1?e.log(e.tetrate(i,a+1,e.dOne,r),i):e.log(e.log(e.tetrate(i,a+2,e.dOne,r),i),i):e.dNaN}},{key:"lambertw",value:function(){if(this.lt(-.3678794411710499))throw Error("lambertw is unimplemented for results less than -1, sorry!");if(this.mag<0)return e.fromNumber(v(this.toNumber()));if(0===this.layer)return e.fromNumber(v(this.sign*this.mag));if(1===this.layer)return d(this);if(2===this.layer)return d(this);if(this.layer>=3)return g(this.sign,this.layer-1,this.mag);throw"Unhandled behavior in lambertw()"}},{key:"ssqrt",value:function(){return this.linear_sroot(2)}},{key:"linear_sroot",value:function(t){if(1==t)return this;if(this.eq(e.dInf))return e.dInf;if(!this.isFinite())return e.dNaN;if(t>0&&t<1)return this.root(t);if(t>-2&&t<-1)return e.fromNumber(t).add(2).pow(this.recip());if(t<=0)return e.dNaN;if(t==Number.POSITIVE_INFINITY){var i=this.toNumber();return i.36787944117144233?this.pow(this.recip()):e.dNaN}if(this.eq(1))return e.dOne;if(this.lt(0))return e.dNaN;if(this.lte("1ee-16"))return t%2==1?this:e.dNaN;if(this.gt(1)){var r=e.dTen;this.gte(e.tetrate(10,t,1,!0))&&(r=this.iteratedlog(10,t-1,!0)),t<=1&&(r=this.root(t));for(var n=e.dZero,a=r.layer,s=r.iteratedlog(10,a,!0),u=s,o=s.div(2),h=!0;h;)o=n.add(s).div(2),e.iteratedexp(10,a,o,!0).tetrate(t,1,!0).gt(this)?s=o:n=o,o.eq(u)?h=!1:u=o;return e.iteratedexp(10,a,o,!0)}for(var l=1,g=m(1,10,1),f=m(1,10,1),c=m(1,10,1),y=m(1,1,-16),v=e.dZero,d=m(1,10,1),N=y.pow10().recip(),p=e.dZero,b=N,k=N,M=Math.ceil(t)%2==0,I=0,_=m(1,10,1),F=!1,w=e.dZero,S=!1;l<4;){if(2==l){if(M)break;c=m(1,10,1),y=g,l=3,d=m(1,10,1),_=m(1,10,1)}for(F=!1;y.neq(c);){if(w=y,y.pow10().recip().tetrate(t,1,!0).eq(1)&&y.pow10().recip().lt(.4))N=y.pow10().recip(),b=y.pow10().recip(),k=y.pow10().recip(),p=e.dZero,I=-1,3==l&&(_=y);else if(y.pow10().recip().tetrate(t,1,!0).eq(y.pow10().recip())&&!M&&y.pow10().recip().lt(.4))N=y.pow10().recip(),b=y.pow10().recip(),k=y.pow10().recip(),p=e.dZero,I=0;else if(y.pow10().recip().tetrate(t,1,!0).eq(y.pow10().recip().mul(2).tetrate(t,1,!0)))N=y.pow10().recip(),b=e.dZero,k=N.mul(2),p=N,I=M?-1:0;else{for(v=y.mul(12e-17),N=y.pow10().recip(),b=y.add(v).pow10().recip(),p=N.sub(b),k=N.add(p);b.tetrate(t,1,!0).eq(N.tetrate(t,1,!0))||k.tetrate(t,1,!0).eq(N.tetrate(t,1,!0))||b.gte(N)||k.lte(N);)v=v.mul(2),b=y.add(v).pow10().recip(),p=N.sub(b),k=N.add(p);if((1==l&&k.tetrate(t,1,!0).gt(N.tetrate(t,1,!0))&&b.tetrate(t,1,!0).gt(N.tetrate(t,1,!0))||3==l&&k.tetrate(t,1,!0).lt(N.tetrate(t,1,!0))&&b.tetrate(t,1,!0).lt(N.tetrate(t,1,!0)))&&(_=y),k.tetrate(t,1,!0).lt(N.tetrate(t,1,!0)))I=-1;else if(M)I=1;else if(3==l&&y.gt_tolerance(g,1e-8))I=0;else{for(;b.tetrate(t,1,!0).eq_tolerance(N.tetrate(t,1,!0),1e-8)||k.tetrate(t,1,!0).eq_tolerance(N.tetrate(t,1,!0),1e-8)||b.gte(N)||k.lte(N);)v=v.mul(2),b=y.add(v).pow10().recip(),p=N.sub(b),k=N.add(p);I=k.tetrate(t,1,!0).sub(N.tetrate(t,1,!0)).lt(N.tetrate(t,1,!0).sub(b.tetrate(t,1,!0)))?0:1}}if(-1==I&&(S=!0),1==l&&1==I||3==l&&0!=I)if(c.eq(m(1,10,1)))y=y.mul(2);else{var q=!1;if(F&&(1==I&&1==l||-1==I&&3==l)&&(q=!0),y=y.add(c).div(2),q)break}else if(c.eq(m(1,10,1)))c=y,y=y.div(2);else{var x=!1;if(F&&(1==I&&1==l||-1==I&&3==l)&&(x=!0),c=c.sub(d),y=y.sub(d),x)break}if(c.sub(y).div(2).abs().gt(d.mul(1.5))&&(F=!0),d=c.sub(y).div(2).abs(),y.gt("1e18"))break;if(y.eq(w))break}if(y.gt("1e18"))break;if(!S)break;if(_==m(1,10,1))break;1==l?g=_:3==l&&(f=_),l++}c=g;for(var E=y=m(1,1,-18),T=e.dZero,O=!0;O;)if(T=c.eq(m(1,10,1))?y.mul(2):c.add(y).div(2),e.pow(10,T).recip().tetrate(t,1,!0).gt(this)?y=T:c=T,T.eq(E)?O=!1:E=T,y.gt("1e18"))return e.dNaN;if(T.eq_tolerance(g,1e-15)){if(f.eq(m(1,10,1)))return e.dNaN;for(c=m(1,10,1),E=y=f,T=e.dZero,O=!0;O;)if(T=c.eq(m(1,10,1))?y.mul(2):c.add(y).div(2),e.pow(10,T).recip().tetrate(t,1,!0).gt(this)?y=T:c=T,T.eq(E)?O=!1:E=T,y.gt("1e18"))return e.dNaN;return T.pow10().recip()}return T.pow10().recip()}},{key:"pentate",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:2,i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:g(1,0,1),r=arguments.length>2&&void 0!==arguments[2]&&arguments[2];i=l(i);var n=t,a=n-(t=Math.trunc(t));0!==a&&(i.eq(e.dOne)?(++t,i=e.fromNumber(a)):i=this.eq(10)?i.layeradd10(a,r):i.layeradd(a,this,r));for(var s=0;s10)return i}return i}},{key:"sin",value:function(){return this.mag<0?this:0===this.layer?e.fromNumber(Math.sin(this.sign*this.mag)):g(0,0,0)}},{key:"cos",value:function(){return this.mag<0?e.dOne:0===this.layer?e.fromNumber(Math.cos(this.sign*this.mag)):g(0,0,0)}},{key:"tan",value:function(){return this.mag<0?this:0===this.layer?e.fromNumber(Math.tan(this.sign*this.mag)):g(0,0,0)}},{key:"asin",value:function(){return this.mag<0?this:0===this.layer?e.fromNumber(Math.asin(this.sign*this.mag)):g(Number.NaN,Number.NaN,Number.NaN)}},{key:"acos",value:function(){return this.mag<0?e.fromNumber(Math.acos(this.toNumber())):0===this.layer?e.fromNumber(Math.acos(this.sign*this.mag)):g(Number.NaN,Number.NaN,Number.NaN)}},{key:"atan",value:function(){return this.mag<0?this:0===this.layer?e.fromNumber(Math.atan(this.sign*this.mag)):e.fromNumber(Math.atan(Infinity*this.sign))}},{key:"sinh",value:function(){return this.exp().sub(this.negate().exp()).div(2)}},{key:"cosh",value:function(){return this.exp().add(this.negate().exp()).div(2)}},{key:"tanh",value:function(){return this.sinh().div(this.cosh())}},{key:"asinh",value:function(){return e.ln(this.add(this.sqr().add(1).sqrt()))}},{key:"acosh",value:function(){return e.ln(this.add(this.sqr().sub(1).sqrt()))}},{key:"atanh",value:function(){return this.abs().gte(1)?g(Number.NaN,Number.NaN,Number.NaN):e.ln(this.add(1).div(e.fromNumber(1).sub(this))).div(2)}},{key:"ascensionPenalty",value:function(t){return 0===t?this:this.root(e.pow(10,t))}},{key:"egg",value:function(){return this.add(9)}},{key:"lessThanOrEqualTo",value:function(t){return this.cmp(t)<1}},{key:"lessThan",value:function(t){return this.cmp(t)<0}},{key:"greaterThanOrEqualTo",value:function(t){return this.cmp(t)>-1}},{key:"greaterThan",value:function(t){return this.cmp(t)>0}}],[{key:"fromComponents",value:function(t,i,r){return(new e).fromComponents(t,i,r)}},{key:"fromComponents_noNormalize",value:function(t,i,r){return(new e).fromComponents_noNormalize(t,i,r)}},{key:"fromMantissaExponent",value:function(t,i){return(new e).fromMantissaExponent(t,i)}},{key:"fromMantissaExponent_noNormalize",value:function(t,i){return(new e).fromMantissaExponent_noNormalize(t,i)}},{key:"fromDecimal",value:function(t){return(new e).fromDecimal(t)}},{key:"fromNumber",value:function(t){return(new e).fromNumber(t)}},{key:"fromString",value:function(t){var i=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return(new e).fromString(t,i)}},{key:"fromValue",value:function(t){return(new e).fromValue(t)}},{key:"fromValue_noAlloc",value:function(t){if(t instanceof e)return t;if("string"==typeof t){var i=e.fromStringCache.get(t);return void 0!==i?i:e.fromString(t)}return"number"==typeof t?e.fromNumber(t):e.dZero}},{key:"abs",value:function(t){return l(t).abs()}},{key:"neg",value:function(t){return l(t).neg()}},{key:"negate",value:function(t){return l(t).neg()}},{key:"negated",value:function(t){return l(t).neg()}},{key:"sign",value:function(t){return l(t).sign}},{key:"sgn",value:function(t){return l(t).sign}},{key:"round",value:function(t){return l(t).round()}},{key:"floor",value:function(t){return l(t).floor()}},{key:"ceil",value:function(t){return l(t).ceil()}},{key:"trunc",value:function(t){return l(t).trunc()}},{key:"add",value:function(t,e){return l(t).add(e)}},{key:"plus",value:function(t,e){return l(t).add(e)}},{key:"sub",value:function(t,e){return l(t).sub(e)}},{key:"subtract",value:function(t,e){return l(t).sub(e)}},{key:"minus",value:function(t,e){return l(t).sub(e)}},{key:"mul",value:function(t,e){return l(t).mul(e)}},{key:"multiply",value:function(t,e){return l(t).mul(e)}},{key:"times",value:function(t,e){return l(t).mul(e)}},{key:"div",value:function(t,e){return l(t).div(e)}},{key:"divide",value:function(t,e){return l(t).div(e)}},{key:"recip",value:function(t){return l(t).recip()}},{key:"reciprocal",value:function(t){return l(t).recip()}},{key:"reciprocate",value:function(t){return l(t).reciprocate()}},{key:"mod",value:function(t,e){return l(t).mod(e)}},{key:"modulo",value:function(t,e){return l(t).modulo(e)}},{key:"modular",value:function(t,e){return l(t).modular(e)}},{key:"cmp",value:function(t,e){return l(t).cmp(e)}},{key:"cmpabs",value:function(t,e){return l(t).cmpabs(e)}},{key:"compare",value:function(t,e){return l(t).cmp(e)}},{key:"isNaN",value:function(t){function e(e){return t.apply(this,arguments)}return e.toString=function(){return t.toString()},e}((function(t){return t=l(t),isNaN(t.sign)||isNaN(t.layer)||isNaN(t.mag)}))},{key:"isFinite",value:function(t){function e(e){return t.apply(this,arguments)}return e.toString=function(){return t.toString()},e}((function(t){return t=l(t),isFinite(t.sign)&&isFinite(t.layer)&&isFinite(t.mag)}))},{key:"eq",value:function(t,e){return l(t).eq(e)}},{key:"equals",value:function(t,e){return l(t).eq(e)}},{key:"neq",value:function(t,e){return l(t).neq(e)}},{key:"notEquals",value:function(t,e){return l(t).notEquals(e)}},{key:"lt",value:function(t,e){return l(t).lt(e)}},{key:"lte",value:function(t,e){return l(t).lte(e)}},{key:"gt",value:function(t,e){return l(t).gt(e)}},{key:"gte",value:function(t,e){return l(t).gte(e)}},{key:"max",value:function(t,e){return l(t).max(e)}},{key:"min",value:function(t,e){return l(t).min(e)}},{key:"minabs",value:function(t,e){return l(t).minabs(e)}},{key:"maxabs",value:function(t,e){return l(t).maxabs(e)}},{key:"clamp",value:function(t,e,i){return l(t).clamp(e,i)}},{key:"clampMin",value:function(t,e){return l(t).clampMin(e)}},{key:"clampMax",value:function(t,e){return l(t).clampMax(e)}},{key:"cmp_tolerance",value:function(t,e,i){return l(t).cmp_tolerance(e,i)}},{key:"compare_tolerance",value:function(t,e,i){return l(t).cmp_tolerance(e,i)}},{key:"eq_tolerance",value:function(t,e,i){return l(t).eq_tolerance(e,i)}},{key:"equals_tolerance",value:function(t,e,i){return l(t).eq_tolerance(e,i)}},{key:"neq_tolerance",value:function(t,e,i){return l(t).neq_tolerance(e,i)}},{key:"notEquals_tolerance",value:function(t,e,i){return l(t).notEquals_tolerance(e,i)}},{key:"lt_tolerance",value:function(t,e,i){return l(t).lt_tolerance(e,i)}},{key:"lte_tolerance",value:function(t,e,i){return l(t).lte_tolerance(e,i)}},{key:"gt_tolerance",value:function(t,e,i){return l(t).gt_tolerance(e,i)}},{key:"gte_tolerance",value:function(t,e,i){return l(t).gte_tolerance(e,i)}},{key:"pLog10",value:function(t){return l(t).pLog10()}},{key:"absLog10",value:function(t){return l(t).absLog10()}},{key:"log10",value:function(t){return l(t).log10()}},{key:"log",value:function(t,e){return l(t).log(e)}},{key:"log2",value:function(t){return l(t).log2()}},{key:"ln",value:function(t){return l(t).ln()}},{key:"logarithm",value:function(t,e){return l(t).logarithm(e)}},{key:"pow",value:function(t,e){return l(t).pow(e)}},{key:"pow10",value:function(t){return l(t).pow10()}},{key:"root",value:function(t,e){return l(t).root(e)}},{key:"factorial",value:function(t,e){return l(t).factorial()}},{key:"gamma",value:function(t,e){return l(t).gamma()}},{key:"lngamma",value:function(t,e){return l(t).lngamma()}},{key:"exp",value:function(t){return l(t).exp()}},{key:"sqr",value:function(t){return l(t).sqr()}},{key:"sqrt",value:function(t){return l(t).sqrt()}},{key:"cube",value:function(t){return l(t).cube()}},{key:"cbrt",value:function(t){return l(t).cbrt()}},{key:"tetrate",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:g(1,0,1),r=arguments.length>3&&void 0!==arguments[3]&&arguments[3];return l(t).tetrate(e,i,r)}},{key:"iteratedexp",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:g(1,0,1),r=arguments.length>3&&void 0!==arguments[3]&&arguments[3];return l(t).iteratedexp(e,i,r)}},{key:"iteratedlog",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:10,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1,r=arguments.length>3&&void 0!==arguments[3]&&arguments[3];return l(t).iteratedlog(e,i,r)}},{key:"layeradd10",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return l(t).layeradd10(e,i)}},{key:"layeradd",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:10,r=arguments.length>3&&void 0!==arguments[3]&&arguments[3];return l(t).layeradd(e,i,r)}},{key:"slog",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:10,i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return l(t).slog(e,100,i)}},{key:"lambertw",value:function(t){return l(t).lambertw()}},{key:"ssqrt",value:function(t){return l(t).ssqrt()}},{key:"linear_sroot",value:function(t,e){return l(t).linear_sroot(e)}},{key:"pentate",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:g(1,0,1),r=arguments.length>3&&void 0!==arguments[3]&&arguments[3];return l(t).pentate(e,i,r)}},{key:"sin",value:function(t){return l(t).sin()}},{key:"cos",value:function(t){return l(t).cos()}},{key:"tan",value:function(t){return l(t).tan()}},{key:"asin",value:function(t){return l(t).asin()}},{key:"acos",value:function(t){return l(t).acos()}},{key:"atan",value:function(t){return l(t).atan()}},{key:"sinh",value:function(t){return l(t).sinh()}},{key:"cosh",value:function(t){return l(t).cosh()}},{key:"tanh",value:function(t){return l(t).tanh()}},{key:"asinh",value:function(t){return l(t).asinh()}},{key:"acosh",value:function(t){return l(t).acosh()}},{key:"atanh",value:function(t){return l(t).atanh()}},{key:"affordGeometricSeries",value:function(t,e,i,r){return this.affordGeometricSeries_core(l(t),l(e),l(i),r)}},{key:"sumGeometricSeries",value:function(t,e,i,r){return this.sumGeometricSeries_core(t,l(e),l(i),r)}},{key:"affordArithmeticSeries",value:function(t,e,i,r){return this.affordArithmeticSeries_core(l(t),l(e),l(i),l(r))}},{key:"sumArithmeticSeries",value:function(t,e,i,r){return this.sumArithmeticSeries_core(l(t),l(e),l(i),l(r))}},{key:"efficiencyOfPurchase",value:function(t,e,i){return this.efficiencyOfPurchase_core(l(t),l(e),l(i))}},{key:"randomDecimalForTesting",value:function(t){if(20*Math.random()<1)return g(0,0,0);var e=Math.random()>.5?1:-1;if(20*Math.random()<1)return g(e,0,1);var i=Math.floor(Math.random()*(t+1)),r=0===i?616*Math.random()-308:16*Math.random();Math.random()>.9&&(r=Math.trunc(r));var n=Math.pow(10,r);return Math.random()>.9&&(n=Math.trunc(n)),m(e,i,n)}},{key:"affordGeometricSeries_core",value:function(t,i,r,n){var a=i.mul(r.pow(n));return e.floor(t.div(a).mul(r.sub(1)).add(1).log10().div(r.log10()))}},{key:"sumGeometricSeries_core",value:function(t,i,r,n){return i.mul(r.pow(n)).mul(e.sub(1,r.pow(t))).div(e.sub(1,r))}},{key:"affordArithmeticSeries_core",value:function(t,e,i,r){var n=e.add(r.mul(i)).sub(i.div(2)),a=n.pow(2);return n.neg().add(a.add(i.mul(t).mul(2)).sqrt()).div(i).floor()}},{key:"sumArithmeticSeries_core",value:function(t,e,i,r){var n=e.add(r.mul(i));return t.div(2).mul(n.mul(2).plus(t.sub(1).mul(i)))}},{key:"efficiencyOfPurchase_core",value:function(t,e,i){return t.div(e).add(t.div(i))}},{key:"slog_critical",value:function(t,i){return t>10?i-1:e.critical_section(t,i,h)}},{key:"tetrate_critical",value:function(t,i){return e.critical_section(t,i,o)}},{key:"critical_section",value:function(t,e,i){(e*=10)<0&&(e=0),e>10&&(e=10),t<2&&(t=2),t>10&&(t=10);for(var r=0,n=0,a=0;at){var s=(t-u[a])/(u[a+1]-u[a]);r=i[a][Math.floor(e)]*(1-s)+i[a+1][Math.floor(e)]*s,n=i[a][Math.ceil(e)]*(1-s)+i[a+1][Math.ceil(e)]*s;break}}var o=e-Math.floor(e);return r<=0||n<=0?r*(1-o)+n*o:Math.pow(t,Math.log(r)/Math.log(t)*(1-o)+Math.log(n)/Math.log(t)*o)}}]),e}();return N.dZero=g(0,0,0),N.dOne=g(1,0,1),N.dNegOne=g(-1,0,1),N.dTwo=g(1,0,2),N.dTen=g(1,0,10),N.dNaN=g(Number.NaN,Number.NaN,Number.NaN),N.dInf=g(1,Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY),N.dNegInf=g(-1,Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY),N.dNumberMax=m(1,0,Number.MAX_VALUE),N.dNumberMin=m(1,0,Number.MIN_VALUE),N.fromStringCache=new r(1023),l=N.fromValue_noAlloc,m=N.fromComponents,g=N.fromComponents_noNormalize,N.fromMantissaExponent,N.fromMantissaExponent_noNormalize,N})); +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).Decimal=t()}(this,(function(){"use strict";function e(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function t(e,t){for(var r=0;rthis.maxSize;){var i=this.last;this.map.delete(i.key),this.last=i.prev,this.last.next=void 0}}}}]),t}(),a=r((function t(r,i){e(this,t),this.next=void 0,this.prev=void 0,this.key=r,this.value=i})),n=Math.log10(9e15),s=function(){for(var e=[],t=-323;t<=308;t++)e.push(Number("1e"+t));return function(t){return e[t+323]}}(),u=[2,Math.E,3,4,5,6,7,8,9,10],o=[[1,1.0891180521811203,1.1789767925673957,1.2701455431742086,1.3632090180450092,1.4587818160364217,1.5575237916251419,1.6601571006859253,1.767485818836978,1.8804192098842727,2],[1,1.1121114330934079,1.231038924931609,1.3583836963111375,1.4960519303993531,1.6463542337511945,1.8121385357018724,1.996971324618307,2.2053895545527546,2.4432574483385254,Math.E],[1,1.1187738849693603,1.2464963939368214,1.38527004705667,1.5376664685821402,1.7068895236551784,1.897001227148399,2.1132403089001035,2.362480153784171,2.6539010333870774,3],[1,1.1367350847096405,1.2889510672956703,1.4606478703324786,1.6570295196661111,1.8850062585672889,2.1539465047453485,2.476829779693097,2.872061932789197,3.3664204535587183,4],[1,1.1494592900767588,1.319708228183931,1.5166291280087583,1.748171114438024,2.0253263297298045,2.3636668498288547,2.7858359149579424,3.3257226212448145,4.035730287722532,5],[1,1.159225940787673,1.343712473580932,1.5611293155111927,1.8221199554561318,2.14183924486326,2.542468319282638,3.0574682501653316,3.7390572020926873,4.6719550537360774,6],[1,1.1670905356972596,1.3632807444991446,1.5979222279405536,1.8842640123816674,2.2416069644878687,2.69893426559423,3.3012632110403577,4.121250340630164,5.281493033448316,7],[1,1.1736630594087796,1.379783782386201,1.6292821855668218,1.9378971836180754,2.3289975651071977,2.8384347394720835,3.5232708454565906,4.478242031114584,5.868592169644505,8],[1,1.1793017514670474,1.394054150657457,1.65664127441059,1.985170999970283,2.4069682290577457,2.9647310119960752,3.7278665320924946,4.814462547283592,6.436522247411611,9],[1,1.1840100246247336,1.4061375836156955,1.6802272208863964,2.026757028388619,2.4770056063449646,3.080525271755482,3.9191964192627284,5.135152840833187,6.989961179534715,10]],l=[[-1,-.9194161097107025,-.8335625019330468,-.7425599821143978,-.6466611521029437,-.5462617907227869,-.4419033816638769,-.3342645487554494,-.224140440909962,-.11241087890006762,0],[-1,-.90603157029014,-.80786507256596,-.7064666939634,-.60294836853664,-.49849837513117,-.39430303318768,-.29147201034755,-.19097820800866,-.09361896280296,0],[-1,-.9021579584316141,-.8005762598234203,-.6964780623319391,-.5911906810998454,-.486050182576545,-.3823089430815083,-.28106046722897615,-.1831906535795894,-.08935809204418144,0],[-1,-.8917227442365535,-.781258746326964,-.6705130326902455,-.5612813129406509,-.4551067709033134,-.35319256652135966,-.2563741554088552,-.1651412821106526,-.0796919581982668,0],[-1,-.8843387974366064,-.7678744063886243,-.6529563724510552,-.5415870994657841,-.4352842206588936,-.33504449124791424,-.24138853420685147,-.15445285440944467,-.07409659641336663,0],[-1,-.8786709358426346,-.7577735191184886,-.6399546189952064,-.527284921869926,-.4211627631006314,-.3223479611761232,-.23107655627789858,-.1472057700818259,-.07035171210706326,0],[-1,-.8740862815291583,-.7497032990976209,-.6297119746181752,-.5161838335958787,-.41036238255751956,-.31277212146489963,-.2233976621705518,-.1418697367979619,-.06762117662323441,0],[-1,-.8702632331800649,-.7430366914122081,-.6213373075161548,-.5072025698095242,-.40171437727184167,-.30517930701410456,-.21736343968190863,-.137710238299109,-.06550774483471955,0],[-1,-.8670016295947213,-.7373984232432306,-.6143173985094293,-.49973884395492807,-.394584953527678,-.2989649949848695,-.21245647317021688,-.13434688362382652,-.0638072667348083,0],[-1,-.8641642839543857,-.732534623168535,-.6083127477059322,-.4934049257184696,-.3885773075899922,-.29376029055315767,-.2083678561173622,-.13155653399373268,-.062401588652553186,0]],h=function(e){return b.fromValue_noAlloc(e)},m=function(e,t,r){return b.fromComponents(e,t,r)},g=function(e,t,r){return b.fromComponents_noNormalize(e,t,r)},f=function(e,t){var r=t+1,i=Math.ceil(Math.log10(Math.abs(e))),a=Math.round(e*Math.pow(10,r-i))*Math.pow(10,i-r);return parseFloat(a.toFixed(Math.max(r-i,0)))},c=function(e){return Math.sign(e)*Math.log10(Math.abs(e))},N=.5671432904097838,v=function(e){var t,r,i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1e-10,a=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];if(!Number.isFinite(e))return e;if(a){if(0===e)return e;if(1===e)return N;t=e<10?0:Math.log(e)-Math.log(Math.log(e))}else{if(0===e)return-1/0;t=e<=-.1?-2:Math.log(-e)-Math.log(-Math.log(-e))}for(var n=0;n<100;++n){if(r=(e*Math.exp(-t)+t*t)/(t+1),Math.abs(r-t)1&&void 0!==arguments[1]?arguments[1]:1e-10,s=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];if(!Number.isFinite(e.mag))return new b(e);if(s){if(e.eq(b.dZero))return g(0,0,0);if(e.eq(b.dOne))return b.fromNumber(N);t=b.ln(e)}else{if(e.eq(b.dZero))return g(-1,Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY);t=b.ln(e.neg())}for(var u=0;u<100;++u){if(r=t.neg().exp(),i=t.sub(e.mul(r)),a=t.sub(i.div(t.add(1).sub(t.add(2).mul(i).div(b.mul(2,t).add(2))))),b.abs(a.sub(t)).lt(b.abs(a).mul(n)))return a;t=a}throw Error("Iteration failed to converge: ".concat(e.toString()))}var b=function(){function t(r){e(this,t),this.sign=0,this.mag=0,this.layer=0,r instanceof t?this.fromDecimal(r):"number"==typeof r?this.fromNumber(r):"string"==typeof r&&this.fromString(r)}return r(t,[{key:"m",get:function(){if(0===this.sign)return 0;if(0===this.layer){var e,t=Math.floor(Math.log10(this.mag));return e=5e-324===this.mag?5:this.mag/s(t),this.sign*e}if(1===this.layer){var r=this.mag-Math.floor(this.mag);return this.sign*Math.pow(10,r)}return this.sign},set:function(e){this.layer<=2?this.fromMantissaExponent(e,this.e):(this.sign=Math.sign(e),0===this.sign&&(this.layer=0,this.exponent=0))}},{key:"e",get:function(){return 0===this.sign?0:0===this.layer?Math.floor(Math.log10(this.mag)):1===this.layer?Math.floor(this.mag):2===this.layer?Math.floor(Math.sign(this.mag)*Math.pow(10,Math.abs(this.mag))):this.mag*Number.POSITIVE_INFINITY},set:function(e){this.fromMantissaExponent(this.m,e)}},{key:"s",get:function(){return this.sign},set:function(e){0===e?(this.sign=0,this.layer=0,this.mag=0):this.sign=e}},{key:"mantissa",get:function(){return this.m},set:function(e){this.m=e}},{key:"exponent",get:function(){return this.e},set:function(e){this.e=e}},{key:"normalize",value:function(){if(0===this.sign||0===this.mag&&0===this.layer||this.mag===Number.NEGATIVE_INFINITY&&this.layer>0&&Number.isFinite(this.layer))return this.sign=0,this.mag=0,this.layer=0,this;if(0===this.layer&&this.mag<0&&(this.mag=-this.mag,this.sign=-this.sign),this.mag===Number.POSITIVE_INFINITY||this.layer===Number.POSITIVE_INFINITY||this.mag===Number.NEGATIVE_INFINITY||this.layer===Number.NEGATIVE_INFINITY)return this.mag=Number.POSITIVE_INFINITY,this.layer=Number.POSITIVE_INFINITY,this;if(0===this.layer&&this.mag<1/9e15)return this.layer+=1,this.mag=Math.log10(this.mag),this;var e=Math.abs(this.mag),t=Math.sign(this.mag);if(e>=9e15)return this.layer+=1,this.mag=t*Math.log10(e),this;for(;e0;)this.layer-=1,0===this.layer?this.mag=Math.pow(10,this.mag):(this.mag=t*Math.pow(10,e),e=Math.abs(this.mag),t=Math.sign(this.mag));return 0===this.layer&&(this.mag<0?(this.mag=-this.mag,this.sign=-this.sign):0===this.mag&&(this.sign=0)),(Number.isNaN(this.sign)||Number.isNaN(this.layer)||Number.isNaN(this.mag))&&(this.sign=Number.NaN,this.layer=Number.NaN,this.mag=Number.NaN),this}},{key:"fromComponents",value:function(e,t,r){return this.sign=e,this.layer=t,this.mag=r,this.normalize(),this}},{key:"fromComponents_noNormalize",value:function(e,t,r){return this.sign=e,this.layer=t,this.mag=r,this}},{key:"fromMantissaExponent",value:function(e,t){return this.layer=1,this.sign=Math.sign(e),e=Math.abs(e),this.mag=t+Math.log10(e),this.normalize(),this}},{key:"fromMantissaExponent_noNormalize",value:function(e,t){return this.fromMantissaExponent(e,t),this}},{key:"fromDecimal",value:function(e){return this.sign=e.sign,this.layer=e.layer,this.mag=e.mag,this}},{key:"fromNumber",value:function(e){return this.mag=Math.abs(e),this.sign=Math.sign(e),this.layer=0,this.normalize(),this}},{key:"fromString",value:function(e){var r=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=e,a=t.fromStringCache.get(i);if(void 0!==a)return this.fromDecimal(a);var n=(e=e.replace(",","")).split("^^^");if(2===n.length){var s=parseFloat(n[0]),u=parseFloat(n[1]),o=n[1].split(";"),l=1;if(2===o.length&&(l=parseFloat(o[1]),isFinite(l)||(l=1)),isFinite(s)&&isFinite(u)){var g=t.pentate(s,u,l,r);return this.sign=g.sign,this.layer=g.layer,this.mag=g.mag,t.fromStringCache.maxSize>=1&&t.fromStringCache.set(i,t.fromDecimal(this)),this}}var f=e.split("^^");if(2===f.length){var N=parseFloat(f[0]),v=parseFloat(f[1]),y=f[1].split(";"),b=1;if(2===y.length&&(b=parseFloat(y[1]),isFinite(b)||(b=1)),isFinite(N)&&isFinite(v)){var d=t.tetrate(N,v,b,r);return this.sign=d.sign,this.layer=d.layer,this.mag=d.mag,t.fromStringCache.maxSize>=1&&t.fromStringCache.set(i,t.fromDecimal(this)),this}}var p,k,I=e.split("^");if(2===I.length){var M=parseFloat(I[0]),w=parseFloat(I[1]);if(isFinite(M)&&isFinite(w)){var _=t.pow(M,w);return this.sign=_.sign,this.layer=_.layer,this.mag=_.mag,t.fromStringCache.maxSize>=1&&t.fromStringCache.set(i,t.fromDecimal(this)),this}}var F=(e=e.trim().toLowerCase()).split("pt");if(2===F.length){p=10;var S=!1;"-"==F[0][0]&&(S=!0,F[0]=F[0].slice(1)),k=parseFloat(F[0]),F[1]=F[1].replace("(",""),F[1]=F[1].replace(")","");var q=parseFloat(F[1]);if(isFinite(q)||(q=1),isFinite(p)&&isFinite(k)){var T=t.tetrate(p,k,q,r);return this.sign=T.sign,this.layer=T.layer,this.mag=T.mag,t.fromStringCache.maxSize>=1&&t.fromStringCache.set(i,t.fromDecimal(this)),S&&(this.sign*=-1),this}}if(2===(F=e.split("p")).length){p=10;var E=!1;"-"==F[0][0]&&(E=!0,F[0]=F[0].slice(1)),k=parseFloat(F[0]),F[1]=F[1].replace("(",""),F[1]=F[1].replace(")","");var x=parseFloat(F[1]);if(isFinite(x)||(x=1),isFinite(p)&&isFinite(k)){var O=t.tetrate(p,k,x,r);return this.sign=O.sign,this.layer=O.layer,this.mag=O.mag,t.fromStringCache.maxSize>=1&&t.fromStringCache.set(i,t.fromDecimal(this)),E&&(this.sign*=-1),this}}if(2===(F=e.split("f")).length){p=10;var V=!1;"-"==F[0][0]&&(V=!0,F[0]=F[0].slice(1)),F[0]=F[0].replace("(",""),F[0]=F[0].replace(")","");var P=parseFloat(F[0]);if(F[1]=F[1].replace("(",""),F[1]=F[1].replace(")",""),k=parseFloat(F[1]),isFinite(P)||(P=1),isFinite(p)&&isFinite(k)){var Y=t.tetrate(p,k,P,r);return this.sign=Y.sign,this.layer=Y.layer,this.mag=Y.mag,t.fromStringCache.maxSize>=1&&t.fromStringCache.set(i,t.fromDecimal(this)),V&&(this.sign*=-1),this}}var C=e.split("e"),z=C.length-1;if(0===z){var D=parseFloat(e);if(isFinite(D))return this.fromNumber(D),t.fromStringCache.size>=1&&t.fromStringCache.set(i,t.fromDecimal(this)),this}else if(1===z){var A=parseFloat(e);if(isFinite(A)&&0!==A)return this.fromNumber(A),t.fromStringCache.maxSize>=1&&t.fromStringCache.set(i,t.fromDecimal(this)),this}var Z=e.split("e^");if(2===Z.length){this.sign=1,"-"==Z[0].charAt(0)&&(this.sign=-1);for(var G="",L=0;L=43&&j<=57||101===j))return this.layer=parseFloat(G),this.mag=parseFloat(Z[1].substr(L+1)),this.normalize(),t.fromStringCache.maxSize>=1&&t.fromStringCache.set(i,t.fromDecimal(this)),this;G+=Z[1].charAt(L)}}if(z<1)return this.sign=0,this.layer=0,this.mag=0,t.fromStringCache.maxSize>=1&&t.fromStringCache.set(i,t.fromDecimal(this)),this;var W=parseFloat(C[0]);if(0===W)return this.sign=0,this.layer=0,this.mag=0,t.fromStringCache.maxSize>=1&&t.fromStringCache.set(i,t.fromDecimal(this)),this;var B=parseFloat(C[C.length-1]);if(z>=2){var U=parseFloat(C[C.length-2]);isFinite(U)&&(B*=Math.sign(U),B+=c(U))}if(isFinite(W))if(1===z)this.sign=Math.sign(W),this.layer=1,this.mag=B+Math.log10(Math.abs(W));else{if(this.sign=Math.sign(W),this.layer=z,2===z){var J=t.mul(m(1,2,B),h(W));return this.sign=J.sign,this.layer=J.layer,this.mag=J.mag,t.fromStringCache.maxSize>=1&&t.fromStringCache.set(i,t.fromDecimal(this)),this}this.mag=B}else this.sign="-"===C[0]?-1:1,this.layer=z,this.mag=B;return this.normalize(),t.fromStringCache.maxSize>=1&&t.fromStringCache.set(i,t.fromDecimal(this)),this}},{key:"fromValue",value:function(e){return e instanceof t?this.fromDecimal(e):"number"==typeof e?this.fromNumber(e):"string"==typeof e?this.fromString(e):(this.sign=0,this.layer=0,this.mag=0,this)}},{key:"toNumber",value:function(){return this.mag===Number.POSITIVE_INFINITY&&this.layer===Number.POSITIVE_INFINITY&&1===this.sign?Number.POSITIVE_INFINITY:this.mag===Number.POSITIVE_INFINITY&&this.layer===Number.POSITIVE_INFINITY&&-1===this.sign?Number.NEGATIVE_INFINITY:Number.isFinite(this.layer)?0===this.layer?this.sign*this.mag:1===this.layer?this.sign*Math.pow(10,this.mag):this.mag>0?this.sign>0?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:0:Number.NaN}},{key:"mantissaWithDecimalPlaces",value:function(e){return isNaN(this.m)?Number.NaN:0===this.m?0:f(this.m,e)}},{key:"magnitudeWithDecimalPlaces",value:function(e){return isNaN(this.mag)?Number.NaN:0===this.mag?0:f(this.mag,e)}},{key:"toString",value:function(){return isNaN(this.layer)||isNaN(this.sign)||isNaN(this.mag)?"NaN":this.mag===Number.POSITIVE_INFINITY||this.layer===Number.POSITIVE_INFINITY?1===this.sign?"Infinity":"-Infinity":0===this.layer?this.mag<1e21&&this.mag>1e-7||0===this.mag?(this.sign*this.mag).toString():this.m+"e"+this.e:1===this.layer?this.m+"e"+this.e:this.layer<=5?(-1===this.sign?"-":"")+"e".repeat(this.layer)+this.mag:(-1===this.sign?"-":"")+"(e^"+this.layer+")"+this.mag}},{key:"toExponential",value:function(e){return 0===this.layer?(this.sign*this.mag).toExponential(e):this.toStringWithDecimalPlaces(e)}},{key:"toFixed",value:function(e){return 0===this.layer?(this.sign*this.mag).toFixed(e):this.toStringWithDecimalPlaces(e)}},{key:"toPrecision",value:function(e){return this.e<=-7?this.toExponential(e-1):e>this.e?this.toFixed(e-this.exponent-1):this.toExponential(e-1)}},{key:"valueOf",value:function(){return this.toString()}},{key:"toJSON",value:function(){return this.toString()}},{key:"toStringWithDecimalPlaces",value:function(e){return 0===this.layer?this.mag<1e21&&this.mag>1e-7||0===this.mag?(this.sign*this.mag).toFixed(e):f(this.m,e)+"e"+f(this.e,e):1===this.layer?f(this.m,e)+"e"+f(this.e,e):this.layer<=5?(-1===this.sign?"-":"")+"e".repeat(this.layer)+f(this.mag,e):(-1===this.sign?"-":"")+"(e^"+this.layer+")"+f(this.mag,e)}},{key:"abs",value:function(){return g(0===this.sign?0:1,this.layer,this.mag)}},{key:"neg",value:function(){return g(-this.sign,this.layer,this.mag)}},{key:"negate",value:function(){return this.neg()}},{key:"negated",value:function(){return this.neg()}},{key:"sgn",value:function(){return this.sign}},{key:"round",value:function(){return this.mag<0?g(0,0,0):0===this.layer?m(this.sign,0,Math.round(this.mag)):new t(this)}},{key:"floor",value:function(){return this.mag<0?-1===this.sign?g(-1,0,1):g(0,0,0):-1===this.sign?this.neg().ceil().neg():0===this.layer?m(this.sign,0,Math.floor(this.mag)):new t(this)}},{key:"ceil",value:function(){return this.mag<0?1===this.sign?g(1,0,1):g(0,0,0):-1===this.sign?this.neg().floor().neg():0===this.layer?m(this.sign,0,Math.ceil(this.mag)):new t(this)}},{key:"trunc",value:function(){return this.mag<0?g(0,0,0):0===this.layer?m(this.sign,0,Math.trunc(this.mag)):new t(this)}},{key:"add",value:function(e){var r,i,a=h(e);if(this.eq(t.dInf)&&a.eq(t.dNegInf)||this.eq(t.dNegInf)&&a.eq(t.dInf))return g(Number.NaN,Number.NaN,Number.NaN);if(!Number.isFinite(this.layer))return new t(this);if(!Number.isFinite(a.layer))return new t(a);if(0===this.sign)return new t(a);if(0===a.sign)return new t(this);if(this.sign===-a.sign&&this.layer===a.layer&&this.mag===a.mag)return g(0,0,0);if(this.layer>=2||a.layer>=2)return this.maxabs(a);if(t.cmpabs(this,a)>0?(r=new t(this),i=new t(a)):(r=new t(a),i=new t(this)),0===r.layer&&0===i.layer)return t.fromNumber(r.sign*r.mag+i.sign*i.mag);var n=r.layer*Math.sign(r.mag),s=i.layer*Math.sign(i.mag);if(n-s>=2)return r;if(0===n&&-1===s){if(Math.abs(i.mag-Math.log10(r.mag))>17)return r;var u=Math.pow(10,Math.log10(r.mag)-i.mag),o=i.sign+r.sign*u;return m(Math.sign(o),1,i.mag+Math.log10(Math.abs(o)))}if(1===n&&0===s){if(Math.abs(r.mag-Math.log10(i.mag))>17)return r;var l=Math.pow(10,r.mag-Math.log10(i.mag)),f=i.sign+r.sign*l;return m(Math.sign(f),1,Math.log10(i.mag)+Math.log10(Math.abs(f)))}if(Math.abs(r.mag-i.mag)>17)return r;var c=Math.pow(10,r.mag-i.mag),N=i.sign+r.sign*c;return m(Math.sign(N),1,i.mag+Math.log10(Math.abs(N)))}},{key:"plus",value:function(e){return this.add(e)}},{key:"sub",value:function(e){return this.add(h(e).neg())}},{key:"subtract",value:function(e){return this.sub(e)}},{key:"minus",value:function(e){return this.sub(e)}},{key:"mul",value:function(e){var r,i,a=h(e);if(this.eq(t.dInf)&&a.eq(t.dNegInf)||this.eq(t.dNegInf)&&a.eq(t.dInf))return g(-1,Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY);if(this.mag==Number.POSITIVE_INFINITY&&a.eq(t.dZero)||this.eq(t.dZero)&&this.mag==Number.POSITIVE_INFINITY)return g(Number.NaN,Number.NaN,Number.NaN);if(!Number.isFinite(this.layer))return new t(this);if(!Number.isFinite(a.layer))return new t(a);if(0===this.sign||0===a.sign)return g(0,0,0);if(this.layer===a.layer&&this.mag===-a.mag)return g(this.sign*a.sign,0,1);if(this.layer>a.layer||this.layer==a.layer&&Math.abs(this.mag)>Math.abs(a.mag)?(r=new t(this),i=new t(a)):(r=new t(a),i=new t(this)),0===r.layer&&0===i.layer)return t.fromNumber(r.sign*i.sign*r.mag*i.mag);if(r.layer>=3||r.layer-i.layer>=2)return m(r.sign*i.sign,r.layer,r.mag);if(1===r.layer&&0===i.layer)return m(r.sign*i.sign,1,r.mag+Math.log10(i.mag));if(1===r.layer&&1===i.layer)return m(r.sign*i.sign,1,r.mag+i.mag);if(2===r.layer&&1===i.layer){var n=m(Math.sign(r.mag),r.layer-1,Math.abs(r.mag)).add(m(Math.sign(i.mag),i.layer-1,Math.abs(i.mag)));return m(r.sign*i.sign,n.layer+1,n.sign*n.mag)}if(2===r.layer&&2===i.layer){var s=m(Math.sign(r.mag),r.layer-1,Math.abs(r.mag)).add(m(Math.sign(i.mag),i.layer-1,Math.abs(i.mag)));return m(r.sign*i.sign,s.layer+1,s.sign*s.mag)}throw Error("Bad arguments to mul: "+this+", "+e)}},{key:"multiply",value:function(e){return this.mul(e)}},{key:"times",value:function(e){return this.mul(e)}},{key:"div",value:function(e){var t=h(e);return this.mul(t.recip())}},{key:"divide",value:function(e){return this.div(e)}},{key:"divideBy",value:function(e){return this.div(e)}},{key:"dividedBy",value:function(e){return this.div(e)}},{key:"recip",value:function(){return 0===this.mag?g(Number.NaN,Number.NaN,Number.NaN):this.mag===Number.POSITIVE_INFINITY?g(0,0,0):0===this.layer?m(this.sign,0,1/this.mag):m(this.sign,this.layer,-this.mag)}},{key:"reciprocal",value:function(){return this.recip()}},{key:"reciprocate",value:function(){return this.recip()}},{key:"mod",value:function(e){var r=h(e).abs();if(r.eq(t.dZero))return g(0,0,0);var i=this.toNumber(),a=r.toNumber();return isFinite(i)&&isFinite(a)&&0!=i&&0!=a?new t(i%a):this.sub(r).eq(this)?g(0,0,0):r.sub(this).eq(r)?new t(this):-1==this.sign?this.abs().mod(r).neg():this.sub(this.div(r).floor().mul(r))}},{key:"modulo",value:function(e){return this.mod(e)}},{key:"modular",value:function(e){return this.mod(e)}},{key:"cmp",value:function(e){var t=h(e);return this.sign>t.sign?1:this.sign0?this.layer:-this.layer,i=t.mag>0?t.layer:-t.layer;return r>i?1:rt.mag?1:this.mag0?new t(r):new t(this)}},{key:"clamp",value:function(e,t){return this.max(e).min(t)}},{key:"clampMin",value:function(e){return this.max(e)}},{key:"clampMax",value:function(e){return this.min(e)}},{key:"cmp_tolerance",value:function(e,t){var r=h(e);return this.eq_tolerance(r,t)?0:this.cmp(r)}},{key:"compare_tolerance",value:function(e,t){return this.cmp_tolerance(e,t)}},{key:"eq_tolerance",value:function(e,t){var r=h(e);if(null==t&&(t=1e-7),this.sign!==r.sign)return!1;if(Math.abs(this.layer-r.layer)>1)return!1;var i=this.mag,a=r.mag;return this.layer>r.layer&&(a=c(a)),this.layer0?m(Math.sign(this.mag),this.layer-1,Math.abs(this.mag)):m(1,0,Math.log10(this.mag))}},{key:"log10",value:function(){return this.sign<=0?g(Number.NaN,Number.NaN,Number.NaN):this.layer>0?m(Math.sign(this.mag),this.layer-1,Math.abs(this.mag)):m(this.sign,0,Math.log10(this.mag))}},{key:"log",value:function(e){return e=h(e),this.sign<=0||e.sign<=0||1===e.sign&&0===e.layer&&1===e.mag?g(Number.NaN,Number.NaN,Number.NaN):0===this.layer&&0===e.layer?m(this.sign,0,Math.log(this.mag)/Math.log(e.mag)):t.div(this.log10(),e.log10())}},{key:"log2",value:function(){return this.sign<=0?g(Number.NaN,Number.NaN,Number.NaN):0===this.layer?m(this.sign,0,Math.log2(this.mag)):1===this.layer?m(Math.sign(this.mag),0,3.321928094887362*Math.abs(this.mag)):2===this.layer?m(Math.sign(this.mag),1,Math.abs(this.mag)+.5213902276543247):m(Math.sign(this.mag),this.layer-1,Math.abs(this.mag))}},{key:"ln",value:function(){return this.sign<=0?g(Number.NaN,Number.NaN,Number.NaN):0===this.layer?m(this.sign,0,Math.log(this.mag)):1===this.layer?m(Math.sign(this.mag),0,2.302585092994046*Math.abs(this.mag)):2===this.layer?m(Math.sign(this.mag),1,Math.abs(this.mag)+.36221568869946325):m(Math.sign(this.mag),this.layer-1,Math.abs(this.mag))}},{key:"logarithm",value:function(e){return this.log(e)}},{key:"pow",value:function(e){var r=h(e),i=new t(this),a=new t(r);if(0===i.sign)return a.eq(0)?g(1,0,1):i;if(1===i.sign&&0===i.layer&&1===i.mag)return i;if(0===a.sign)return g(1,0,1);if(1===a.sign&&0===a.layer&&1===a.mag)return i;var n=i.absLog10().mul(a).pow10();return-1===this.sign?Math.abs(a.toNumber()%2)%2==1?n.neg():Math.abs(a.toNumber()%2)%2==0?n:g(Number.NaN,Number.NaN,Number.NaN):n}},{key:"pow10",value:function(){if(this.eq(t.dInf))return g(1,Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY);if(this.eq(t.dNegInf))return g(0,0,0);if(!Number.isFinite(this.layer)||!Number.isFinite(this.mag))return g(Number.NaN,Number.NaN,Number.NaN);var e=new t(this);if(0===e.layer){var r=Math.pow(10,e.sign*e.mag);if(Number.isFinite(r)&&Math.abs(r)>=.1)return m(1,0,r);if(0===e.sign)return g(1,0,1);e=g(e.sign,e.layer+1,Math.log10(e.mag))}return e.sign>0&&e.mag>=0?m(e.sign,e.layer+1,e.mag):e.sign<0&&e.mag>=0?m(-e.sign,e.layer+1,-e.mag):g(1,0,1)}},{key:"pow_base",value:function(e){return h(e).pow(this)}},{key:"root",value:function(e){var t=h(e);return this.pow(t.recip())}},{key:"factorial",value:function(){return this.mag<0||0===this.layer?this.add(1).gamma():1===this.layer?t.exp(t.mul(this,t.ln(this).sub(1))):t.exp(this)}},{key:"gamma",value:function(){if(this.mag<0)return this.recip();if(0===this.layer){if(this.lt(g(1,0,24)))return t.fromNumber(function(e){if(!isFinite(e))return e;if(e<-50)return e===Math.trunc(e)?Number.NEGATIVE_INFINITY:0;for(var t=1;e<10;)t*=e,++e;var r=.9189385332046727;r+=((e-=1)+.5)*Math.log(e),r-=e;var i=e*e,a=e;return r+=1/(12*a),r-=1/(360*(a*=i)),r+=1/(1260*(a*=i)),r-=1/(1680*(a*=i)),r+=1/(1188*(a*=i)),r-=691/(360360*(a*=i)),r+=7/(1092*(a*=i)),r-=3617/(122400*(a*=i)),Math.exp(r)/t}(this.sign*this.mag));var e=this.mag-1,r=.9189385332046727;r+=(e+.5)*Math.log(e);var i=e*e,a=e,n=12*a,s=1/n,u=(r-=e)+s;if(u===r)return t.exp(r);if((u=(r=u)-(s=1/(n=360*(a*=i))))===r)return t.exp(r);r=u;var o=1/(n=1260*(a*=i));return r+=o,r-=o=1/(n=1680*(a*=i)),t.exp(r)}return 1===this.layer?t.exp(t.mul(this,t.ln(this).sub(1))):t.exp(this)}},{key:"lngamma",value:function(){return this.gamma().ln()}},{key:"exp",value:function(){return this.mag<0?g(1,0,1):0===this.layer&&this.mag<=709.7?t.fromNumber(Math.exp(this.sign*this.mag)):0===this.layer?m(1,1,this.sign*Math.log10(Math.E)*this.mag):1===this.layer?m(1,2,this.sign*(Math.log10(.4342944819032518)+this.mag)):m(1,this.layer+1,this.sign*this.mag)}},{key:"sqr",value:function(){return this.pow(2)}},{key:"sqrt",value:function(){if(0===this.layer)return t.fromNumber(Math.sqrt(this.sign*this.mag));if(1===this.layer)return m(1,2,Math.log10(this.mag)-.3010299956639812);var e=t.div(g(this.sign,this.layer-1,this.mag),g(1,0,2));return e.layer+=1,e.normalize(),e}},{key:"cube",value:function(){return this.pow(3)}},{key:"cbrt",value:function(){return this.pow(1/3)}},{key:"tetrate",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:2,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:g(1,0,1),i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(1===e)return t.pow(this,r);if(0===e)return new t(r);if(this.eq(t.dOne))return g(1,0,1);if(this.eq(-1))return t.pow(this,r);if(e===Number.POSITIVE_INFINITY){var a=this.toNumber();if(a<=1.444667861009766&&a>=.06598803584531254){var n=t.ln(this).neg(),s=n.lambertw().div(n);if(a<1)return s;var u=n.lambertw(!1).div(n);return a>1.444667861009099&&(s=u=t.fromNumber(Math.E)),(r=h(r)).eq(u)?u:r.lt(u)?s:g(1,Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY)}return a>1.444667861009766?g(1,Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY):g(Number.NaN,Number.NaN,Number.NaN)}if(this.eq(t.dZero)){var o=Math.abs((e+1)%2);return o>1&&(o=2-o),t.fromNumber(o)}if(e<0)return t.iteratedlog(r,this,-e,i);r=new t(r);var l=e,m=l-(e=Math.trunc(e));if(this.gt(t.dZero)&&(this.lt(1)||this.lte(1.444667861009766)&&r.lte(t.ln(this).neg().lambertw(!1).div(t.ln(this).neg())))&&(l>1e4||!i)){var f=Math.min(1e4,e);r=r.eq(t.dOne)?this.pow(m):this.lt(1)?r.pow(1-m).mul(this.pow(r).pow(m)):r.layeradd(m,this);for(var c=0;c1e4&&Math.ceil(l)%2==1?this.pow(r):r}0!==m&&(r.eq(t.dOne)?this.gt(10)||i?r=this.pow(m):(r=t.fromNumber(t.tetrate_critical(this.toNumber(),m)),this.lt(2)&&(r=r.sub(1).mul(this.minus(1)).plus(1))):r=this.eq(10)?r.layeradd10(m,i):this.lt(1)?r.pow(1-m).mul(this.pow(r).pow(m)):r.layeradd(m,this,i));for(var v=0;v3)return g(r.sign,r.layer+(e-v-1),r.mag);if(v>1e4)return r}return r}},{key:"iteratedexp",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:2,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:g(1,0,1),r=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return this.tetrate(e,t,r)}},{key:"iteratedlog",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:10,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1,i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];if(r<0)return t.tetrate(e,-r,this,i);e=h(e);var a=t.fromDecimal(this),n=r,s=n-(r=Math.trunc(r));if(a.layer-e.layer>3){var u=Math.min(r,a.layer-e.layer-3);r-=u,a.layer-=u}for(var o=0;o1e4)return a}return s>0&&s<1&&(a=e.eq(10)?a.layeradd10(-s,i):a.layeradd(-s,e,i)),a}},{key:"slog",value:function(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:10,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:100,i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],a=.001,n=!1,s=!1,u=this.slog_internal(e,i).toNumber(),o=1;o1&&s!=h&&(n=!0),s=h,n?a/=2:a*=2,u+=a=Math.abs(a)*(h?-1:1),0===a)break}return t.fromNumber(u)}},{key:"slog_internal",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:10,r=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if((e=h(e)).lte(t.dZero))return g(Number.NaN,Number.NaN,Number.NaN);if(e.eq(t.dOne))return g(Number.NaN,Number.NaN,Number.NaN);if(e.lt(t.dOne))return this.eq(t.dOne)?g(0,0,0):this.eq(t.dZero)?g(-1,0,1):g(Number.NaN,Number.NaN,Number.NaN);if(this.mag<0||this.eq(t.dZero))return g(-1,0,1);if(e.lt(1.444667861009766)){var i=t.ln(e).neg(),a=i.lambertw().div(i);if(this.eq(a))return g(1,Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY);if(this.gt(a))return g(Number.NaN,Number.NaN,Number.NaN)}var n=0,s=t.fromDecimal(this);if(s.layer-e.layer>3){var u=s.layer-e.layer-3;n+=u,s.layer-=u}for(var o=0;o<100;++o)if(s.lt(t.dZero))s=t.pow(e,s),n-=1;else{if(s.lte(t.dOne))return r?t.fromNumber(n+s.toNumber()-1):t.fromNumber(n+t.slog_critical(e.toNumber(),s.toNumber()));n+=1,s=t.log(s,e)}return t.fromNumber(n)}},{key:"layeradd10",value:function(e){var r=arguments.length>1&&void 0!==arguments[1]&&arguments[1];e=t.fromValue_noAlloc(e).toNumber();var i=t.fromDecimal(this);if(e>=1){i.mag<0&&i.layer>0?(i.sign=0,i.mag=0,i.layer=0):-1===i.sign&&0==i.layer&&(i.sign=1,i.mag=-i.mag);var a=Math.trunc(e);e-=a,i.layer+=a}if(e<=-1){var n=Math.trunc(e);if(e-=n,i.layer+=n,i.layer<0)for(var s=0;s<100;++s){if(i.layer++,i.mag=Math.log10(i.mag),!isFinite(i.mag))return 0===i.sign&&(i.sign=1),i.layer<0&&(i.layer=0),i.normalize();if(i.layer>=0)break}}for(;i.layer<0;)i.layer++,i.mag=Math.log10(i.mag);return 0===i.sign&&(i.sign=1,0===i.mag&&i.layer>=1&&(i.layer-=1,i.mag=1)),i.normalize(),0!==e?i.layeradd(e,10,r):i}},{key:"layeradd",value:function(e,r){var i=arguments.length>2&&void 0!==arguments[2]&&arguments[2],a=h(r);if(a.gt(1)&&a.lte(1.444667861009766)){var n=t.excess_slog(this,r,i),s=n[0].toNumber(),u=n[1],o=s+e,l=t.ln(r).neg(),m=l.lambertw().div(l),f=l.lambertw(!1).div(l),c=t.dOne;1==u?c=m.mul(f).sqrt():2==u&&(c=f.mul(2));var N=a.pow(c),v=Math.floor(o),y=o-v,b=c.pow(1-y).mul(N.pow(y));return t.tetrate(a,v,b,i)}var d=this.slog(r,100,i).toNumber(),p=d+e;return p>=0?t.tetrate(r,p,t.dOne,i):Number.isFinite(p)?p>=-1?t.log(t.tetrate(r,p+1,t.dOne,i),r):t.log(t.log(t.tetrate(r,p+2,t.dOne,i),r),r):g(Number.NaN,Number.NaN,Number.NaN)}},{key:"lambertw",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];return this.lt(-.3678794411710499)?g(Number.NaN,Number.NaN,Number.NaN):e?this.abs().lt("1e-300")?new t(this):this.mag<0?t.fromNumber(v(this.toNumber())):0===this.layer?t.fromNumber(v(this.sign*this.mag)):this.lt("eee15")?y(this):this.ln():1===this.sign?g(Number.NaN,Number.NaN,Number.NaN):0===this.layer?t.fromNumber(v(this.sign*this.mag,1e-10,!1)):1==this.layer?y(this,1e-10,!1):this.neg().recip().lambertw().neg()}},{key:"ssqrt",value:function(){return this.linear_sroot(2)}},{key:"linear_sroot",value:function(e){if(1==e)return this;if(this.eq(t.dInf))return g(1,Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY);if(!this.isFinite())return g(Number.NaN,Number.NaN,Number.NaN);if(e>0&&e<1)return this.root(e);if(e>-2&&e<-1)return t.fromNumber(e).add(2).pow(this.recip());if(e<=0)return g(Number.NaN,Number.NaN,Number.NaN);if(e==Number.POSITIVE_INFINITY){var r=this.toNumber();return r.36787944117144233?this.pow(this.recip()):g(Number.NaN,Number.NaN,Number.NaN)}if(this.eq(1))return g(1,0,1);if(this.lt(0))return g(Number.NaN,Number.NaN,Number.NaN);if(this.lte("1ee-16"))return e%2==1?new t(this):g(Number.NaN,Number.NaN,Number.NaN);if(this.gt(1)){var i=t.dTen;this.gte(t.tetrate(10,e,1,!0))&&(i=this.iteratedlog(10,e-1,!0)),e<=1&&(i=this.root(e));for(var a=t.dZero,n=i.layer,s=i.iteratedlog(10,n,!0),u=s,o=s.div(2),l=!0;l;)o=a.add(s).div(2),t.iteratedexp(10,n,o,!0).tetrate(e,1,!0).gt(this)?s=o:a=o,o.eq(u)?l=!1:u=o;return t.iteratedexp(10,n,o,!0)}for(var h=1,f=m(1,10,1),c=m(1,10,1),N=m(1,10,1),v=m(1,1,-16),y=t.dZero,b=m(1,10,1),d=v.pow10().recip(),p=t.dZero,k=d,I=d,M=Math.ceil(e)%2==0,w=0,_=m(1,10,1),F=!1,S=t.dZero,q=!1;h<4;){if(2==h){if(M)break;N=m(1,10,1),v=f,h=3,b=m(1,10,1),_=m(1,10,1)}for(F=!1;v.neq(N);){if(S=v,v.pow10().recip().tetrate(e,1,!0).eq(1)&&v.pow10().recip().lt(.4))d=v.pow10().recip(),k=v.pow10().recip(),I=v.pow10().recip(),p=t.dZero,w=-1,3==h&&(_=v);else if(v.pow10().recip().tetrate(e,1,!0).eq(v.pow10().recip())&&!M&&v.pow10().recip().lt(.4))d=v.pow10().recip(),k=v.pow10().recip(),I=v.pow10().recip(),p=t.dZero,w=0;else if(v.pow10().recip().tetrate(e,1,!0).eq(v.pow10().recip().mul(2).tetrate(e,1,!0)))d=v.pow10().recip(),k=t.dZero,I=d.mul(2),p=d,w=M?-1:0;else{for(y=v.mul(12e-17),d=v.pow10().recip(),k=v.add(y).pow10().recip(),p=d.sub(k),I=d.add(p);k.tetrate(e,1,!0).eq(d.tetrate(e,1,!0))||I.tetrate(e,1,!0).eq(d.tetrate(e,1,!0))||k.gte(d)||I.lte(d);)y=y.mul(2),k=v.add(y).pow10().recip(),p=d.sub(k),I=d.add(p);if((1==h&&I.tetrate(e,1,!0).gt(d.tetrate(e,1,!0))&&k.tetrate(e,1,!0).gt(d.tetrate(e,1,!0))||3==h&&I.tetrate(e,1,!0).lt(d.tetrate(e,1,!0))&&k.tetrate(e,1,!0).lt(d.tetrate(e,1,!0)))&&(_=v),I.tetrate(e,1,!0).lt(d.tetrate(e,1,!0)))w=-1;else if(M)w=1;else if(3==h&&v.gt_tolerance(f,1e-8))w=0;else{for(;k.tetrate(e,1,!0).eq_tolerance(d.tetrate(e,1,!0),1e-8)||I.tetrate(e,1,!0).eq_tolerance(d.tetrate(e,1,!0),1e-8)||k.gte(d)||I.lte(d);)y=y.mul(2),k=v.add(y).pow10().recip(),p=d.sub(k),I=d.add(p);w=I.tetrate(e,1,!0).sub(d.tetrate(e,1,!0)).lt(d.tetrate(e,1,!0).sub(k.tetrate(e,1,!0)))?0:1}}if(-1==w&&(q=!0),1==h&&1==w||3==h&&0!=w)if(N.eq(m(1,10,1)))v=v.mul(2);else{var T=!1;if(F&&(1==w&&1==h||-1==w&&3==h)&&(T=!0),v=v.add(N).div(2),T)break}else if(N.eq(m(1,10,1)))N=v,v=v.div(2);else{var E=!1;if(F&&(1==w&&1==h||-1==w&&3==h)&&(E=!0),N=N.sub(b),v=v.sub(b),E)break}if(N.sub(v).div(2).abs().gt(b.mul(1.5))&&(F=!0),b=N.sub(v).div(2).abs(),v.gt("1e18"))break;if(v.eq(S))break}if(v.gt("1e18"))break;if(!q)break;if(_==m(1,10,1))break;1==h?f=_:3==h&&(c=_),h++}N=f;for(var x=v=m(1,1,-18),O=t.dZero,V=!0;V;)if(O=N.eq(m(1,10,1))?v.mul(2):N.add(v).div(2),t.pow(10,O).recip().tetrate(e,1,!0).gt(this)?v=O:N=O,O.eq(x)?V=!1:x=O,v.gt("1e18"))return g(Number.NaN,Number.NaN,Number.NaN);if(O.eq_tolerance(f,1e-15)){if(c.eq(m(1,10,1)))return g(Number.NaN,Number.NaN,Number.NaN);for(N=m(1,10,1),x=v=c,O=t.dZero,V=!0;V;)if(O=N.eq(m(1,10,1))?v.mul(2):N.add(v).div(2),t.pow(10,O).recip().tetrate(e,1,!0).gt(this)?v=O:N=O,O.eq(x)?V=!1:x=O,v.gt("1e18"))return g(Number.NaN,Number.NaN,Number.NaN);return O.pow10().recip()}return O.pow10().recip()}},{key:"pentate",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:2,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:g(1,0,1),i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];r=new t(r);var a=e,n=a-(e=Math.trunc(e));0!==n&&(r.eq(t.dOne)?(++e,r=t.fromNumber(n)):r=this.eq(10)?r.layeradd10(n,i):r.layeradd(n,this,i));for(var s=0;s10)return r}return r}},{key:"sin",value:function(){return this.mag<0?new t(this):0===this.layer?t.fromNumber(Math.sin(this.sign*this.mag)):g(0,0,0)}},{key:"cos",value:function(){return this.mag<0?g(1,0,1):0===this.layer?t.fromNumber(Math.cos(this.sign*this.mag)):g(0,0,0)}},{key:"tan",value:function(){return this.mag<0?new t(this):0===this.layer?t.fromNumber(Math.tan(this.sign*this.mag)):g(0,0,0)}},{key:"asin",value:function(){return this.mag<0?new t(this):0===this.layer?t.fromNumber(Math.asin(this.sign*this.mag)):g(Number.NaN,Number.NaN,Number.NaN)}},{key:"acos",value:function(){return this.mag<0?t.fromNumber(Math.acos(this.toNumber())):0===this.layer?t.fromNumber(Math.acos(this.sign*this.mag)):g(Number.NaN,Number.NaN,Number.NaN)}},{key:"atan",value:function(){return this.mag<0?new t(this):0===this.layer?t.fromNumber(Math.atan(this.sign*this.mag)):t.fromNumber(Math.atan(Infinity*this.sign))}},{key:"sinh",value:function(){return this.exp().sub(this.negate().exp()).div(2)}},{key:"cosh",value:function(){return this.exp().add(this.negate().exp()).div(2)}},{key:"tanh",value:function(){return this.sinh().div(this.cosh())}},{key:"asinh",value:function(){return t.ln(this.add(this.sqr().add(1).sqrt()))}},{key:"acosh",value:function(){return t.ln(this.add(this.sqr().sub(1).sqrt()))}},{key:"atanh",value:function(){return this.abs().gte(1)?g(Number.NaN,Number.NaN,Number.NaN):t.ln(this.add(1).div(t.fromNumber(1).sub(this))).div(2)}},{key:"ascensionPenalty",value:function(e){return 0===e?new t(this):this.root(t.pow(10,e))}},{key:"egg",value:function(){return this.add(9)}},{key:"lessThanOrEqualTo",value:function(e){return this.cmp(e)<1}},{key:"lessThan",value:function(e){return this.cmp(e)<0}},{key:"greaterThanOrEqualTo",value:function(e){return this.cmp(e)>-1}},{key:"greaterThan",value:function(e){return this.cmp(e)>0}}],[{key:"fromComponents",value:function(e,r,i){return(new t).fromComponents(e,r,i)}},{key:"fromComponents_noNormalize",value:function(e,r,i){return(new t).fromComponents_noNormalize(e,r,i)}},{key:"fromMantissaExponent",value:function(e,r){return(new t).fromMantissaExponent(e,r)}},{key:"fromMantissaExponent_noNormalize",value:function(e,r){return(new t).fromMantissaExponent_noNormalize(e,r)}},{key:"fromDecimal",value:function(e){return(new t).fromDecimal(e)}},{key:"fromNumber",value:function(e){return(new t).fromNumber(e)}},{key:"fromString",value:function(e){var r=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return(new t).fromString(e,r)}},{key:"fromValue",value:function(e){return(new t).fromValue(e)}},{key:"fromValue_noAlloc",value:function(e){if(e instanceof t)return e;if("string"==typeof e){var r=t.fromStringCache.get(e);return void 0!==r?r:t.fromString(e)}return"number"==typeof e?t.fromNumber(e):g(0,0,0)}},{key:"abs",value:function(e){return h(e).abs()}},{key:"neg",value:function(e){return h(e).neg()}},{key:"negate",value:function(e){return h(e).neg()}},{key:"negated",value:function(e){return h(e).neg()}},{key:"sign",value:function(e){return h(e).sign}},{key:"sgn",value:function(e){return h(e).sign}},{key:"round",value:function(e){return h(e).round()}},{key:"floor",value:function(e){return h(e).floor()}},{key:"ceil",value:function(e){return h(e).ceil()}},{key:"trunc",value:function(e){return h(e).trunc()}},{key:"add",value:function(e,t){return h(e).add(t)}},{key:"plus",value:function(e,t){return h(e).add(t)}},{key:"sub",value:function(e,t){return h(e).sub(t)}},{key:"subtract",value:function(e,t){return h(e).sub(t)}},{key:"minus",value:function(e,t){return h(e).sub(t)}},{key:"mul",value:function(e,t){return h(e).mul(t)}},{key:"multiply",value:function(e,t){return h(e).mul(t)}},{key:"times",value:function(e,t){return h(e).mul(t)}},{key:"div",value:function(e,t){return h(e).div(t)}},{key:"divide",value:function(e,t){return h(e).div(t)}},{key:"recip",value:function(e){return h(e).recip()}},{key:"reciprocal",value:function(e){return h(e).recip()}},{key:"reciprocate",value:function(e){return h(e).reciprocate()}},{key:"mod",value:function(e,t){return h(e).mod(t)}},{key:"modulo",value:function(e,t){return h(e).modulo(t)}},{key:"modular",value:function(e,t){return h(e).modular(t)}},{key:"cmp",value:function(e,t){return h(e).cmp(t)}},{key:"cmpabs",value:function(e,t){return h(e).cmpabs(t)}},{key:"compare",value:function(e,t){return h(e).cmp(t)}},{key:"isNaN",value:function(e){function t(t){return e.apply(this,arguments)}return t.toString=function(){return e.toString()},t}((function(e){return e=h(e),isNaN(e.sign)||isNaN(e.layer)||isNaN(e.mag)}))},{key:"isFinite",value:function(e){function t(t){return e.apply(this,arguments)}return t.toString=function(){return e.toString()},t}((function(e){return e=h(e),isFinite(e.sign)&&isFinite(e.layer)&&isFinite(e.mag)}))},{key:"eq",value:function(e,t){return h(e).eq(t)}},{key:"equals",value:function(e,t){return h(e).eq(t)}},{key:"neq",value:function(e,t){return h(e).neq(t)}},{key:"notEquals",value:function(e,t){return h(e).notEquals(t)}},{key:"lt",value:function(e,t){return h(e).lt(t)}},{key:"lte",value:function(e,t){return h(e).lte(t)}},{key:"gt",value:function(e,t){return h(e).gt(t)}},{key:"gte",value:function(e,t){return h(e).gte(t)}},{key:"max",value:function(e,t){return h(e).max(t)}},{key:"min",value:function(e,t){return h(e).min(t)}},{key:"minabs",value:function(e,t){return h(e).minabs(t)}},{key:"maxabs",value:function(e,t){return h(e).maxabs(t)}},{key:"clamp",value:function(e,t,r){return h(e).clamp(t,r)}},{key:"clampMin",value:function(e,t){return h(e).clampMin(t)}},{key:"clampMax",value:function(e,t){return h(e).clampMax(t)}},{key:"cmp_tolerance",value:function(e,t,r){return h(e).cmp_tolerance(t,r)}},{key:"compare_tolerance",value:function(e,t,r){return h(e).cmp_tolerance(t,r)}},{key:"eq_tolerance",value:function(e,t,r){return h(e).eq_tolerance(t,r)}},{key:"equals_tolerance",value:function(e,t,r){return h(e).eq_tolerance(t,r)}},{key:"neq_tolerance",value:function(e,t,r){return h(e).neq_tolerance(t,r)}},{key:"notEquals_tolerance",value:function(e,t,r){return h(e).notEquals_tolerance(t,r)}},{key:"lt_tolerance",value:function(e,t,r){return h(e).lt_tolerance(t,r)}},{key:"lte_tolerance",value:function(e,t,r){return h(e).lte_tolerance(t,r)}},{key:"gt_tolerance",value:function(e,t,r){return h(e).gt_tolerance(t,r)}},{key:"gte_tolerance",value:function(e,t,r){return h(e).gte_tolerance(t,r)}},{key:"pLog10",value:function(e){return h(e).pLog10()}},{key:"absLog10",value:function(e){return h(e).absLog10()}},{key:"log10",value:function(e){return h(e).log10()}},{key:"log",value:function(e,t){return h(e).log(t)}},{key:"log2",value:function(e){return h(e).log2()}},{key:"ln",value:function(e){return h(e).ln()}},{key:"logarithm",value:function(e,t){return h(e).logarithm(t)}},{key:"pow",value:function(e,t){return h(e).pow(t)}},{key:"pow10",value:function(e){return h(e).pow10()}},{key:"root",value:function(e,t){return h(e).root(t)}},{key:"factorial",value:function(e,t){return h(e).factorial()}},{key:"gamma",value:function(e,t){return h(e).gamma()}},{key:"lngamma",value:function(e,t){return h(e).lngamma()}},{key:"exp",value:function(e){return h(e).exp()}},{key:"sqr",value:function(e){return h(e).sqr()}},{key:"sqrt",value:function(e){return h(e).sqrt()}},{key:"cube",value:function(e){return h(e).cube()}},{key:"cbrt",value:function(e){return h(e).cbrt()}},{key:"tetrate",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:g(1,0,1),i=arguments.length>3&&void 0!==arguments[3]&&arguments[3];return h(e).tetrate(t,r,i)}},{key:"iteratedexp",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:g(1,0,1),i=arguments.length>3&&void 0!==arguments[3]&&arguments[3];return h(e).iteratedexp(t,r,i)}},{key:"iteratedlog",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:10,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1,i=arguments.length>3&&void 0!==arguments[3]&&arguments[3];return h(e).iteratedlog(t,r,i)}},{key:"layeradd10",value:function(e,t){var r=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return h(e).layeradd10(t,r)}},{key:"layeradd",value:function(e,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:10,i=arguments.length>3&&void 0!==arguments[3]&&arguments[3];return h(e).layeradd(t,r,i)}},{key:"slog",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:10,r=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return h(e).slog(t,100,r)}},{key:"lambertw",value:function(e,t){return h(e).lambertw(t)}},{key:"ssqrt",value:function(e){return h(e).ssqrt()}},{key:"linear_sroot",value:function(e,t){return h(e).linear_sroot(t)}},{key:"pentate",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:g(1,0,1),i=arguments.length>3&&void 0!==arguments[3]&&arguments[3];return h(e).pentate(t,r,i)}},{key:"sin",value:function(e){return h(e).sin()}},{key:"cos",value:function(e){return h(e).cos()}},{key:"tan",value:function(e){return h(e).tan()}},{key:"asin",value:function(e){return h(e).asin()}},{key:"acos",value:function(e){return h(e).acos()}},{key:"atan",value:function(e){return h(e).atan()}},{key:"sinh",value:function(e){return h(e).sinh()}},{key:"cosh",value:function(e){return h(e).cosh()}},{key:"tanh",value:function(e){return h(e).tanh()}},{key:"asinh",value:function(e){return h(e).asinh()}},{key:"acosh",value:function(e){return h(e).acosh()}},{key:"atanh",value:function(e){return h(e).atanh()}},{key:"affordGeometricSeries",value:function(e,t,r,i){return this.affordGeometricSeries_core(h(e),h(t),h(r),i)}},{key:"sumGeometricSeries",value:function(e,t,r,i){return this.sumGeometricSeries_core(e,h(t),h(r),i)}},{key:"affordArithmeticSeries",value:function(e,t,r,i){return this.affordArithmeticSeries_core(h(e),h(t),h(r),h(i))}},{key:"sumArithmeticSeries",value:function(e,t,r,i){return this.sumArithmeticSeries_core(h(e),h(t),h(r),h(i))}},{key:"efficiencyOfPurchase",value:function(e,t,r){return this.efficiencyOfPurchase_core(h(e),h(t),h(r))}},{key:"randomDecimalForTesting",value:function(e){if(20*Math.random()<1)return g(0,0,0);var t=Math.random()>.5?1:-1;if(20*Math.random()<1)return g(t,0,1);var r=Math.floor(Math.random()*(e+1)),i=0===r?616*Math.random()-308:16*Math.random();Math.random()>.9&&(i=Math.trunc(i));var a=Math.pow(10,i);return Math.random()>.9&&(a=Math.trunc(a)),m(t,r,a)}},{key:"affordGeometricSeries_core",value:function(e,r,i,a){var n=r.mul(i.pow(a));return t.floor(e.div(n).mul(i.sub(1)).add(1).log10().div(i.log10()))}},{key:"sumGeometricSeries_core",value:function(e,r,i,a){return r.mul(i.pow(a)).mul(t.sub(1,i.pow(e))).div(t.sub(1,i))}},{key:"affordArithmeticSeries_core",value:function(e,t,r,i){var a=t.add(i.mul(r)).sub(r.div(2)),n=a.pow(2);return a.neg().add(n.add(r.mul(e).mul(2)).sqrt()).div(r).floor()}},{key:"sumArithmeticSeries_core",value:function(e,t,r,i){var a=t.add(i.mul(r));return e.div(2).mul(a.mul(2).plus(e.sub(1).mul(r)))}},{key:"efficiencyOfPurchase_core",value:function(e,t,r){return e.div(t).add(e.div(r))}},{key:"slog_critical",value:function(e,r){return e>10?r-1:t.critical_section(e,r,l)}},{key:"tetrate_critical",value:function(e,r){return t.critical_section(e,r,o)}},{key:"critical_section",value:function(e,t,r){(t*=10)<0&&(t=0),t>10&&(t=10),e<2&&(e=2),e>10&&(e=10);for(var i=0,a=0,n=0;ne){var s=(e-u[n])/(u[n+1]-u[n]);i=r[n][Math.floor(t)]*(1-s)+r[n+1][Math.floor(t)]*s,a=r[n][Math.ceil(t)]*(1-s)+r[n+1][Math.ceil(t)]*s;break}}var o=t-Math.floor(t);return i<=0||a<=0?i*(1-o)+a*o:Math.pow(e,Math.log(i)/Math.log(e)*(1-o)+Math.log(a)/Math.log(e)*o)}},{key:"excess_slog",value:function(e,r){var i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];e=h(e);var a=r=h(r);if(1==(r=r.toNumber())||r<=0)return[g(Number.NaN,Number.NaN,Number.NaN),0];if(r>1.444667861009766)return[e.slog(r,100,i),0];var n=t.ln(r).neg(),s=n.lambertw().div(n),u=t.dInf;if(r>1&&(u=n.lambertw(!1).div(n)),r>1.444667861009099&&(s=u=t.fromNumber(Math.E)),e.lt(s))return[e.slog(r,100,i),0];if(e.eq(s))return[g(1,Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY),0];if(e.eq(u))return[g(1,Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY),2];if(e.gt(u)){var o=u.mul(2),l=a.pow(o),m=0;if(e.gte(o)&&e.lt(l))m=0;else if(e.gte(l)){var f=l;for(m=1;f.lt(e);)if(m+=1,(f=a.pow(f)).layer>3){var c=Math.floor(e.layer-f.layer+1);f=a.iteratedexp(c,f,i),m+=c}f.gt(e)&&(f=f.log(r),m-=1)}else if(e.lt(o)){var N=o;for(m=0;N.gt(e);)N=N.log(r),m-=1}for(var v=0,y=0,b=.5,d=o,p=t.dZero;b>1e-16;){if(y=v+b,d=o.pow(1-y).mul(l.pow(y)),(p=t.iteratedexp(r,m,d)).eq(e))return[new t(m+y),2];p.lt(e)&&(v+=b),b/=2}return p.neq_tolerance(e,1e-7)?[g(Number.NaN,Number.NaN,Number.NaN),0]:[new t(m+v),2]}if(e.lt(u)&&e.gt(s)){var k=s.mul(u).sqrt(),I=a.pow(k),M=0;if(e.lte(k)&&e.gt(I))M=0;else if(e.lte(I)){var w=I;for(M=1;w.gt(e);)w=a.pow(w),M+=1;w.lt(e)&&(w=w.log(r),M-=1)}else if(e.gt(k)){var _=k;for(M=0;_.lt(e);)_=_.log(r),M-=1}for(var F=0,S=0,q=.5,T=k,E=t.dZero;q>1e-16;){if(S=F+q,T=k.pow(1-S).mul(I.pow(S)),(E=t.iteratedexp(r,M,T)).eq(e))return[new t(M+S),1];E.gt(e)&&(F+=q),q/=2}return E.neq_tolerance(e,1e-7)?[g(Number.NaN,Number.NaN,Number.NaN),0]:[new t(M+F),1]}throw new Error("Unhandled behavior in excess_slog")}}]),t}();return b.dZero=g(0,0,0),b.dOne=g(1,0,1),b.dNegOne=g(-1,0,1),b.dTwo=g(1,0,2),b.dTen=g(1,0,10),b.dNaN=g(Number.NaN,Number.NaN,Number.NaN),b.dInf=g(1,Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY),b.dNegInf=g(-1,Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY),b.dNumberMax=m(1,0,Number.MAX_VALUE),b.dNumberMin=m(1,0,Number.MIN_VALUE),b.fromStringCache=new i(1023),h=b.fromValue_noAlloc,m=b.fromComponents,g=b.fromComponents_noNormalize,b.fromMantissaExponent,b.fromMantissaExponent_noNormalize,b})); diff --git a/index.d.ts b/index.d.ts index 0e94102..89f33e9 100644 --- a/index.d.ts +++ b/index.d.ts @@ -481,8 +481,12 @@ export default class Decimal { /** * The Lambert W function, also called the omega function or product logarithm, is the solution W(x) === x*e^x. * https://en.wikipedia.org/wiki/Lambert_W_function + * + * This is a multi-valued function in the complex plane, but only two branches matter for real numbers: the "principal branch" W0, and the "non-principal branch" W_-1. + * W_0 works for any number >= -1/e, but W_-1 only works for negative numbers >= -1/e. + * The "principal" parameter, which is true by default, decides which branch we're looking for: W_0 is used if principal is true, W_-1 is used if principal is false. */ - static lambertw(value: DecimalSource): Decimal; + static lambertw(value: DecimalSource, principal: boolean): Decimal; /** * The super square-root function - what number, tetrated to height 2, equals 'value'? https://en.wikipedia.org/wiki/Tetration#Super-root */ @@ -688,19 +692,19 @@ export default class Decimal { /** * Rounds the Decimal it's called on to the nearest integer. */ - round(): this | Decimal; + round(): Decimal; /** * "Rounds" the Decimal it's called on to the nearest integer that's less than or equal to it. */ - floor(): this | Decimal; + floor(): Decimal; /** * "Rounds" the Decimal it's called on to the nearest integer that's greater than or equal to it. */ - ceil(): this | Decimal; + ceil(): Decimal; /** * Extracts the integer part of the Decimal and returns it. Behaves like floor on positive numbers, but behaves like ceiling on negative numbers. */ - trunc(): this | Decimal; + trunc(): Decimal; /** * Addition: returns the sum of 'this' and 'value'. */ @@ -1082,11 +1086,26 @@ export default class Decimal { * Analytic approximation is not currently supported for bases > 10. */ layeradd(diff: number, base: DecimalSource, linear?: boolean): Decimal; + /** + * A strange version of slog for bases between 1 and e^1/e which can handle values above base^^Infinity. + * Returns a pair of a Decimal and a number, with the number always being 0, 1, or 2. The number indicates what range we're in: + * 0 means we're below the lower solution of b^x = x, and so the normal slog is used. + * 1 means we're between the two solutions of b^x = x, with the geometric mean of the two solutions arbitrarily chosen to be the value with a slog of 0. + * 2 means we're above the upper solution of b^x = x, with (upper solution * 2) arbitrarily chosen to be the value with a slog of 0. + * + * The values returned by this function don't really have much mathematical meaning, but the difference between two values does. + * Therefore, this function is kept private, but it's used for layeradd on these small bases. + */ + private static excess_slog; /** * The Lambert W function, also called the omega function or product logarithm, is the solution W(x) === x*e^x. * https://en.wikipedia.org/wiki/Lambert_W_function + * + * This is a multi-valued function in the complex plane, but only two branches matter for real numbers: the "principal branch" W0, and the "non-principal branch" W_-1. + * W_0 works for any number >= -1/e, but W_-1 only works for nonpositive numbers >= -1/e. + * The "principal" parameter, which is true by default, decides which branch we're looking for: W_0 is used if principal is true, W_-1 is used if principal is false. */ - lambertw(): Decimal; + lambertw(principal?: boolean): Decimal; /** * The super square-root function - what number, tetrated to height 2, equals 'this'? https://en.wikipedia.org/wiki/Tetration#Super-root */ diff --git a/src/index.ts b/src/index.ts index 31a9e1b..ce54e7f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -241,19 +241,19 @@ const f_gamma = function (n: number) { let np = n; l = l + 1 / (12 * np); np = np * n2; - l = l + 1 / (360 * np); + l = l - 1 / (360 * np); np = np * n2; l = l + 1 / (1260 * np); np = np * n2; - l = l + 1 / (1680 * np); + l = l - 1 / (1680 * np); np = np * n2; l = l + 1 / (1188 * np); np = np * n2; - l = l + 691 / (360360 * np); + l = l - 691 / (360360 * np); np = np * n2; l = l + 7 / (1092 * np); np = np * n2; - l = l + 3617 / (122400 * np); + l = l - 3617 / (122400 * np); return Math.exp(l) / scal1; }; @@ -263,24 +263,36 @@ const _EXPN1 = 0.36787944117144232159553; // exp(-1) const OMEGA = 0.56714329040978387299997; // W(1, 0) //from https://math.stackexchange.com/a/465183 // The evaluation can become inaccurate very close to the branch point -const f_lambertw = function (z: number, tol = 1e-10): number { +// Evaluates W(x, 0) if principal is true, W(x, -1) if principal is false +const f_lambertw = function (z: number, tol = 1e-10, principal = true): number { let w; let wn; if (!Number.isFinite(z)) { return z; } - if (z === 0) { - return z; - } - if (z === 1) { - return OMEGA; + if (principal) { + if (z === 0) { + return z; + } + if (z === 1) { + return OMEGA; + } + + if (z < 10) { + w = 0; + } else { + w = Math.log(z) - Math.log(Math.log(z)); + } } + else { + if (z === 0) return -Infinity; - if (z < 10) { - w = 0; - } else { - w = Math.log(z) - Math.log(Math.log(z)); + if (z <= -0.1) { + w = -2; + } else { + w = Math.log(-z) - Math.log(-Math.log(-z)); + } } for (let i = 0; i < 100; ++i) { @@ -300,24 +312,33 @@ const f_lambertw = function (z: number, tol = 1e-10): number { // The evaluation can become inaccurate very close to the branch point // at ``-1/e``. In some corner cases, `lambertw` might currently // fail to converge, or can end up on the wrong branch. -function d_lambertw(z: Decimal, tol = 1e-10): Decimal { +// Evaluates W(x, 0) if principal is true, W(x, -1) if principal is false +function d_lambertw(z: Decimal, tol = 1e-10, principal = true): Decimal { let w; let ew, wewz, wn; if (!Number.isFinite(z.mag)) { - return z; + return new Decimal(z); } - if (z.eq(Decimal.dZero)) { - return z; + if (principal) { + if (z.eq(Decimal.dZero)) { + return FC_NN(0, 0, 0); + } + if (z.eq(Decimal.dOne)) { + //Split out this case because the asymptotic series blows up + return Decimal.fromNumber(OMEGA); + } + + //Get an initial guess for Halley's method + w = Decimal.ln(z); } - if (z.eq(Decimal.dOne)) { - //Split out this case because the asymptotic series blows up - return Decimal.fromNumber(OMEGA); + else { + if (z.eq(Decimal.dZero)) { + return FC_NN(-1, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY); + } + //Get an initial guess for Halley's method + w = Decimal.ln(z.neg()); } - - //Get an initial guess for Halley's method - w = Decimal.ln(z); - //Halley's method; see 5.9 in [1] for (let i = 0; i < 100; ++i) { @@ -348,7 +369,7 @@ export default class Decimal { public static readonly dTen = FC_NN(1, 0, 10); public static readonly dNaN = FC_NN(Number.NaN, Number.NaN, Number.NaN); public static readonly dInf = FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); - public static readonly dNegInf = FC_NN(-1, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY); + public static readonly dNegInf = FC_NN(-1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); public static readonly dNumberMax = FC(1, 0, Number.MAX_VALUE); public static readonly dNumberMin = FC(1, 0, Number.MIN_VALUE); @@ -531,7 +552,7 @@ export default class Decimal { // This should never happen... but some users like Prestige Tree Rewritten // pass undefined values in as DecimalSources, so we should handle this // case to not break them. - return Decimal.dZero; + return FC_NN(0, 0, 0); } } @@ -1229,10 +1250,14 @@ export default class Decimal { /** * The Lambert W function, also called the omega function or product logarithm, is the solution W(x) === x*e^x. - * https://en.wikipedia.org/wiki/Lambert_W_function + * https://en.wikipedia.org/wiki/Lambert_W_function + * + * This is a multi-valued function in the complex plane, but only two branches matter for real numbers: the "principal branch" W0, and the "non-principal branch" W_-1. + * W_0 works for any number >= -1/e, but W_-1 only works for negative numbers >= -1/e. + * The "principal" parameter, which is true by default, decides which branch we're looking for: W_0 is used if principal is true, W_-1 is used if principal is false. */ - public static lambertw(value: DecimalSource): Decimal { - return D(value).lambertw(); + public static lambertw(value: DecimalSource, principal : boolean): Decimal { + return D(value).lambertw(principal); } /** @@ -1552,7 +1577,7 @@ export default class Decimal { Any 0 is totally zero (0, 0, 0) and any NaN is totally NaN (NaN, NaN, NaN). Anything layer 0 has mag 0 OR mag > 1/9e15 and < 9e15. Anything layer 1 or higher has abs(mag) >= 15.954 and < 9e15. - Any positive infinity is (1, Infinity, Infinity) and any negative infinity is (-1, -Infinity, -Infinity). + Any positive infinity is (1, Infinity, Infinity) and any negative infinity is (-1, Infinity, Infinity). We will assume in calculations that all Decimals are either erroneous or satisfy these criteria. (Otherwise: Garbage in, garbage out.) */ @@ -1572,14 +1597,8 @@ export default class Decimal { //Handle infinities if (this.mag === Number.POSITIVE_INFINITY || this.layer === Number.POSITIVE_INFINITY || this.mag === Number.NEGATIVE_INFINITY || this.layer === Number.NEGATIVE_INFINITY) { - if (this.sign == 1) { this.mag = Number.POSITIVE_INFINITY; this.layer = Number.POSITIVE_INFINITY; - } - else if (this.sign == -1) { - this.mag = Number.NEGATIVE_INFINITY - this.layer = Number.NEGATIVE_INFINITY; - } return this; } @@ -1801,6 +1820,11 @@ export default class Decimal { let ptparts = value.split("pt"); if (ptparts.length === 2) { base = 10; + let negative = false; + if (ptparts[0][0] == "-") { + negative = true; + ptparts[0] = ptparts[0].slice(1); + } height = parseFloat(ptparts[0]); ptparts[1] = ptparts[1].replace("(", ""); ptparts[1] = ptparts[1].replace(")", ""); @@ -1816,6 +1840,7 @@ export default class Decimal { if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } + if (negative) this.sign *= -1; return this; } } @@ -1824,6 +1849,11 @@ export default class Decimal { ptparts = value.split("p"); if (ptparts.length === 2) { base = 10; + let negative = false; + if (ptparts[0][0] == "-") { + negative = true; + ptparts[0] = ptparts[0].slice(1); + } height = parseFloat(ptparts[0]); ptparts[1] = ptparts[1].replace("(", ""); ptparts[1] = ptparts[1].replace(")", ""); @@ -1839,6 +1869,7 @@ export default class Decimal { if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } + if (negative) this.sign *= -1; return this; } } @@ -1847,6 +1878,11 @@ export default class Decimal { ptparts = value.split("f"); if (ptparts.length === 2) { base = 10; + let negative = false; + if (ptparts[0][0] == "-") { + negative = true; + ptparts[0] = ptparts[0].slice(1); + } ptparts[0] = ptparts[0].replace("(", ""); ptparts[0] = ptparts[0].replace(")", ""); let payload = parseFloat(ptparts[0]); @@ -1864,6 +1900,7 @@ export default class Decimal { if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } + if (negative) this.sign *= -1; return this; } } @@ -2018,7 +2055,7 @@ export default class Decimal { if (this.mag === Number.POSITIVE_INFINITY && this.layer === Number.POSITIVE_INFINITY && this.sign === 1) { return Number.POSITIVE_INFINITY; } - if (this.mag === Number.NEGATIVE_INFINITY && this.layer === Number.NEGATIVE_INFINITY && this.sign === -1) { + if (this.mag === Number.POSITIVE_INFINITY && this.layer === Number.POSITIVE_INFINITY && this.sign === -1) { return Number.NEGATIVE_INFINITY; } if (!Number.isFinite(this.layer)) { @@ -2073,7 +2110,7 @@ export default class Decimal { if (isNaN(this.layer) || isNaN(this.sign) || isNaN(this.mag)) { return "NaN"; } - if (this.mag === Number.POSITIVE_INFINITY || this.layer === Number.POSITIVE_INFINITY || this.mag === Number.NEGATIVE_INFINITY || this.layer === Number.NEGATIVE_INFINITY) { + if (this.mag === Number.POSITIVE_INFINITY || this.layer === Number.POSITIVE_INFINITY) { return this.sign === 1 ? "Infinity" : "-Infinity"; } @@ -2192,57 +2229,57 @@ export default class Decimal { /** * Rounds the Decimal it's called on to the nearest integer. */ - public round(): this | Decimal { + public round(): Decimal { if (this.mag < 0) { - return Decimal.dZero; + return FC_NN(0, 0, 0); } if (this.layer === 0) { return FC(this.sign, 0, Math.round(this.mag)); } - return this; + return new Decimal(this); } /** * "Rounds" the Decimal it's called on to the nearest integer that's less than or equal to it. */ - public floor(): this | Decimal { + public floor(): Decimal { if (this.mag < 0) { - if (this.sign === -1) return Decimal.dNegOne; - else return Decimal.dZero; + if (this.sign === -1) return FC_NN(-1, 0, 1); + else return FC_NN(0, 0, 0); } if (this.sign === -1) return this.neg().ceil().neg(); if (this.layer === 0) { return FC(this.sign, 0, Math.floor(this.mag)); } - return this; + return new Decimal(this); } /** * "Rounds" the Decimal it's called on to the nearest integer that's greater than or equal to it. */ - public ceil(): this | Decimal { + public ceil(): Decimal { if (this.mag < 0) { - if (this.sign === 1) return Decimal.dOne; //The ceiling function called on something tiny like 10^10^-100 should return 1, since 10^10^-100 is still greater than 0 - else return Decimal.dZero; + if (this.sign === 1) return FC_NN(1, 0, 1); //The ceiling function called on something tiny like 10^10^-100 should return 1, since 10^10^-100 is still greater than 0 + else return FC_NN(0, 0, 0); } if (this.sign === -1) return this.neg().floor().neg(); if (this.layer === 0) { return FC(this.sign, 0, Math.ceil(this.mag)); } - return this; + return new Decimal(this); } /** * Extracts the integer part of the Decimal and returns it. Behaves like floor on positive numbers, but behaves like ceiling on negative numbers. */ - public trunc(): this | Decimal { + public trunc(): Decimal { if (this.mag < 0) { - return Decimal.dZero; + return FC_NN(0, 0, 0); } if (this.layer === 0) { return FC(this.sign, 0, Math.trunc(this.mag)); } - return this; + return new Decimal(this); } /** @@ -2251,20 +2288,25 @@ export default class Decimal { public add(value: DecimalSource): this | Decimal { const decimal = D(value); + //Infinity + -Infinity = NaN + if ((this.eq(Decimal.dInf) && decimal.eq(Decimal.dNegInf)) || (this.eq(Decimal.dNegInf) && decimal.eq(Decimal.dInf))) { + return FC_NN(Number.NaN, Number.NaN, Number.NaN); + } + //inf/nan check if (!Number.isFinite(this.layer)) { - return this; + return new Decimal(this); } if (!Number.isFinite(decimal.layer)) { - return decimal; + return new Decimal(decimal); } //Special case - if one of the numbers is 0, return the other number. if (this.sign === 0) { - return decimal; + return new Decimal(decimal); } if (decimal.sign === 0) { - return this; + return new Decimal(this); } //Special case - Adding a number to its negation produces 0, no matter how large. @@ -2281,11 +2323,11 @@ export default class Decimal { } if (Decimal.cmpabs(this, decimal) > 0) { - a = this; - b = decimal; + a = new Decimal(this); + b = new Decimal(decimal); } else { - a = decimal; - b = this; + a = new Decimal(decimal); + b = new Decimal(this); } if (a.layer === 0 && b.layer === 0) { @@ -2365,12 +2407,22 @@ export default class Decimal { public mul(value: DecimalSource): Decimal { const decimal = D(value); + // Infinity * -Infinity = -Infinity + if ((this.eq(Decimal.dInf) && decimal.eq(Decimal.dNegInf)) || (this.eq(Decimal.dNegInf) && decimal.eq(Decimal.dInf))) { + return FC_NN(-1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); + } + + //Infinity * 0 = NaN + if ((this.mag == Number.POSITIVE_INFINITY && decimal.eq(Decimal.dZero)) || (this.eq(Decimal.dZero) && this.mag == Number.POSITIVE_INFINITY)) { + return FC_NN(Number.NaN, Number.NaN, Number.NaN); + } + //inf/nan check if (!Number.isFinite(this.layer)) { - return this; + return new Decimal(this); } if (!Number.isFinite(decimal.layer)) { - return decimal; + return new Decimal(decimal); } //Special case - if one of the numbers is 0, return 0. @@ -2391,11 +2443,11 @@ export default class Decimal { this.layer > decimal.layer || (this.layer == decimal.layer && Math.abs(this.mag) > Math.abs(decimal.mag)) ) { - a = this; - b = decimal; + a = new Decimal(this); + b = new Decimal(decimal); } else { - a = decimal; - b = this; + a = new Decimal(decimal); + b = new Decimal(this); } if (a.layer === 0 && b.layer === 0) { @@ -2480,8 +2532,12 @@ export default class Decimal { */ public recip(): Decimal { if (this.mag === 0) { - return Decimal.dNaN; - } else if (this.layer === 0) { + return FC_NN(Number.NaN, Number.NaN, Number.NaN); + } + else if (this.mag === Number.POSITIVE_INFINITY) { + return FC_NN(0, 0, 0); + } + else if (this.layer === 0) { return FC(this.sign, 0, 1 / this.mag); } else { return FC(this.sign, this.layer, -this.mag); @@ -2510,7 +2566,7 @@ export default class Decimal { public mod(value: DecimalSource): Decimal { const decimal = D(value).abs(); - if (decimal.eq(Decimal.dZero)) return Decimal.dZero; + if (decimal.eq(Decimal.dZero)) return FC_NN(0, 0, 0); const num_this = this.toNumber(); const num_decimal = decimal.toNumber(); //Special case: To avoid precision issues, if both numbers are valid JS numbers, just call % on those @@ -2519,11 +2575,11 @@ export default class Decimal { } if (this.sub(decimal).eq(this)) { //decimal is too small to register to this - return Decimal.dZero; + return FC_NN(0, 0, 0); } if (decimal.sub(this).eq(decimal)) { //this is too small to register to decimal - return this; + return new Decimal(this); } if (this.sign == -1) return this.abs().mod(decimal).neg(); return this.sub(this.div(decimal).floor().mul(decimal)); @@ -2665,7 +2721,7 @@ export default class Decimal { */ public max(value: DecimalSource): Decimal { const decimal = D(value); - return this.lt(decimal) ? decimal : this; + return this.lt(decimal) ? new Decimal(decimal) : new Decimal(this); } /** @@ -2673,7 +2729,7 @@ export default class Decimal { */ public min(value: DecimalSource): Decimal { const decimal = D(value); - return this.gt(decimal) ? decimal : this; + return this.gt(decimal) ? new Decimal(decimal) : new Decimal(this); } /** @@ -2681,7 +2737,7 @@ export default class Decimal { */ public maxabs(value: DecimalSource): Decimal { const decimal = D(value); - return this.cmpabs(decimal) < 0 ? decimal : this; + return this.cmpabs(decimal) < 0 ? new Decimal(decimal) : new Decimal(this); } /** @@ -2689,7 +2745,7 @@ export default class Decimal { */ public minabs(value: DecimalSource): Decimal { const decimal = D(value); - return this.cmpabs(decimal) > 0 ? decimal : this; + return this.cmpabs(decimal) > 0 ? new Decimal(decimal) : new Decimal(this); } /** @@ -2850,7 +2906,7 @@ export default class Decimal { */ public pLog10(): Decimal { if (this.lt(Decimal.dZero)) { - return Decimal.dZero; + return FC_NN(0, 0, 0); } return this.log10(); } @@ -2860,7 +2916,7 @@ export default class Decimal { */ public absLog10(): Decimal { if (this.sign === 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } else if (this.layer > 0) { return FC(Math.sign(this.mag), this.layer - 1, Math.abs(this.mag)); } else { @@ -2874,7 +2930,7 @@ export default class Decimal { */ public log10(): Decimal { if (this.sign <= 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } else if (this.layer > 0) { return FC(Math.sign(this.mag), this.layer - 1, Math.abs(this.mag)); } else { @@ -2888,13 +2944,13 @@ export default class Decimal { public log(base: DecimalSource): Decimal { base = D(base); if (this.sign <= 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } if (base.sign <= 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } if (base.sign === 1 && base.layer === 0 && base.mag === 1) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } else if (this.layer === 0 && base.layer === 0) { return FC(this.sign, 0, Math.log(this.mag) / Math.log(base.mag)); } @@ -2907,7 +2963,7 @@ export default class Decimal { */ public log2(): Decimal { if (this.sign <= 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } else if (this.layer === 0) { return FC(this.sign, 0, Math.log2(this.mag)); } else if (this.layer === 1) { @@ -2924,7 +2980,7 @@ export default class Decimal { */ public ln(): Decimal { if (this.sign <= 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } else if (this.layer === 0) { return FC(this.sign, 0, Math.log(this.mag)); } else if (this.layer === 1) { @@ -2948,8 +3004,8 @@ export default class Decimal { */ public pow(value: DecimalSource): Decimal { const decimal = D(value); - const a = this; - const b = decimal; + const a = new Decimal(this); + const b = new Decimal(decimal); //special case: if a is 0, then return 0 (UNLESS b is 0, then return 1) if (a.sign === 0) { @@ -2976,7 +3032,7 @@ export default class Decimal { } else if (Math.abs(b.toNumber() % 2) % 2 === 0) { return result; } - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } return result; @@ -2994,11 +3050,17 @@ export default class Decimal { 4) negative sign, negative mag (-e-15, -ee-15): layer 0 case would have been handled in the Math.pow check, so just return 1 */ + if (this.eq(Decimal.dInf)) { + return FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); + } + if (this.eq(Decimal.dNegInf)) { + return FC_NN(0, 0, 0); + } if (!Number.isFinite(this.layer) || !Number.isFinite(this.mag)) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } - let a: Decimal = this; + let a: Decimal = new Decimal(this); //handle layer 0 case - if no precision is lost just use Math.pow, else promote one layer if (a.layer === 0) { @@ -3007,7 +3069,7 @@ export default class Decimal { return FC(1, 0, newmag); } else { if (a.sign === 0) { - return Decimal.dOne; + return FC_NN(1, 0, 1); } else { a = FC_NN(a.sign, a.layer + 1, Math.log10(a.mag)); } @@ -3022,7 +3084,7 @@ export default class Decimal { return FC(-a.sign, a.layer + 1, -a.mag); } //both the negative mag cases are identical: one +/- rounding error - return Decimal.dOne; + return FC_NN(1, 0, 1); } /** @@ -3122,7 +3184,7 @@ export default class Decimal { */ public exp(): Decimal { if (this.mag < 0) { - return Decimal.dOne; + return FC_NN(1, 0, 1); } if (this.layer === 0 && this.mag <= 709.7) { return Decimal.fromNumber(Math.exp(this.sign * this.mag)); @@ -3195,7 +3257,7 @@ export default class Decimal { } //1^^x == 1 if (this.eq(Decimal.dOne)) { - return Decimal.dOne; + return FC_NN(1, 0, 1); } //-1^^x == -1 if (this.eq(-1)) { @@ -3206,21 +3268,27 @@ export default class Decimal { const this_num = this.toNumber(); //within the convergence range? if (this_num <= 1.44466786100976613366 && this_num >= 0.06598803584531253708) { + const negln = Decimal.ln(this).neg(); + //For bases above 1, b^x = x has two solutions. The lower solution is a stable equilibrium, the upper solution is an unstable equilibrium. + let lower = negln.lambertw().div(negln); + // However, if the base is below 1, there's only the stable equilibrium solution. + if (this_num < 1) return lower; + let upper = negln.lambertw(false).div(negln); //hotfix for the very edge of the number range not being handled properly if (this_num > 1.444667861009099) { - return Decimal.fromNumber(Math.E); + lower = upper = Decimal.fromNumber(Math.E); } - //Formula for infinite height power tower. - const negln = Decimal.ln(this).neg(); - return negln.lambertw().div(negln); + payload = D(payload); + if (payload.eq(upper)) return upper; + else if (payload.lt(upper)) return lower; + else return FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); } else if (this_num > 1.44466786100976613366) { //explodes to infinity - // TODO: replace this with Decimal.dInf - return Decimal.fromNumber(Number.POSITIVE_INFINITY); + return FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); } else { //0.06598803584531253708 > this_num >= 0: never converges //this_num < 0: quickly becomes a complex number - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } } @@ -3238,15 +3306,18 @@ export default class Decimal { return Decimal.iteratedlog(payload, this, -height, linear); } - payload = D(payload); + payload = new Decimal(payload); const oldheight = height; height = Math.trunc(height); const fracheight = oldheight - height; - if (this.gt(Decimal.dZero) && this.lte(1.44466786100976613366) && (oldheight > 10000 || !linear)) { - //similar to 0^^n, flip-flops between two values, converging slowly (or if it's below 0.06598803584531253708, never. so once again, the fractional part at the end will be a linear approximation (TODO: again pending knowledge of how to approximate better, although tbh I think it should in reality just be NaN) - height = Math.min(10000, height); - for (let i = 0; i < height; ++i) { + if (this.gt(Decimal.dZero) && (this.lt(1) || (this.lte(1.44466786100976613366) && payload.lte(Decimal.ln(this).neg().lambertw(false).div(Decimal.ln(this).neg())))) && (oldheight > 10000 || !linear)) { + //similar to 0^^n, flip-flops between two values, converging slowly (or if it's below 0.06598803584531253708, never). So once again, the fractional part at the beginning will be a linear approximation (TODO: again pending knowledge of how to approximate better, although tbh I think it should in reality just be NaN) + const limitheight = Math.min(10000, height); + if (payload.eq(Decimal.dOne)) payload = this.pow(fracheight); + else if (this.lt(1)) payload = payload.pow(1 - fracheight).mul(this.pow(payload).pow(fracheight)); + else payload = payload.layeradd(fracheight, this); + for (let i = 0; i < limitheight; ++i) { const old_payload: Decimal = payload; payload = this.pow(payload); //stop early if we converge @@ -3254,14 +3325,8 @@ export default class Decimal { return payload; } } - if (fracheight != 0 || oldheight > 10000) { - const next_payload = this.pow(payload); - if (oldheight <= 10000 || Math.ceil(oldheight) % 2 == 0) { - return payload.mul(1 - fracheight).add(next_payload.mul(fracheight)); - } - else { - return payload.mul(fracheight).add(next_payload.mul(1 - fracheight)); - } + if (oldheight > 10000 && Math.ceil(oldheight) % 2 == 1) { + return this.pow(payload); } return payload; } @@ -3284,7 +3349,11 @@ export default class Decimal { } else { if (this.eq(10)) { payload = payload.layeradd10(fracheight, linear); - } else { + } + else if (this.lt(1)) { + payload = payload.pow(1 - fracheight).mul(this.pow(payload).pow(fracheight)); + } + else { payload = payload.layeradd(fracheight, this, linear); } } @@ -3363,7 +3432,7 @@ export default class Decimal { if (fraction > 0 && fraction < 1) { if (base.eq(10)) { result = result.layeradd10(-fraction, linear); - } else { + } else { //I have no clue what a fractional times on a base below 1 should even mean, so I'm not going to bother - just let it be NaN (TODO: come up with what the answer actually should be) result = result.layeradd(-fraction, base, linear); } } @@ -3421,28 +3490,34 @@ export default class Decimal { //special cases: //slog base 0 or lower is NaN if (base.lte(Decimal.dZero)) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //slog base 1 is NaN if (base.eq(Decimal.dOne)) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //need to handle these small, wobbling bases specially if (base.lt(Decimal.dOne)) { if (this.eq(Decimal.dOne)) { - return Decimal.dZero; + return FC_NN(0, 0, 0); } if (this.eq(Decimal.dZero)) { - return Decimal.dNegOne; + return FC_NN(-1, 0, 1); } //0 < this < 1: ambiguous (happens multiple times) //this < 0: impossible (as far as I can tell) //this > 1: partially complex (http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html base 0.25 for proof) - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //slog_n(0) is -1 if (this.mag < 0 || this.eq(Decimal.dZero)) { - return Decimal.dNegOne; + return FC_NN(-1, 0, 1); + } + if (base.lt(1.44466786100976613366)) { + const negln = Decimal.ln(base).neg(); + let infTower = negln.lambertw().div(negln); + if (this.eq(infTower)) return FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); + if (this.gt(infTower)) return FC_NN(Number.NaN, Number.NaN, Number.NaN); } let result = 0; @@ -3618,12 +3693,30 @@ export default class Decimal { * Analytic approximation is not currently supported for bases > 10. */ public layeradd(diff: number, base: DecimalSource, linear = false): Decimal { - const slogthis = this.slog(base).toNumber(); + let baseD = D(base); + if (baseD.gt(1) && baseD.lte(1.44466786100976613366)) { + const excessSlog = Decimal.excess_slog(this, base, linear); + const slogthis = excessSlog[0].toNumber(); + const range = excessSlog[1]; + const slogdest = slogthis + diff; + const negln = Decimal.ln(base).neg(); + let lower = negln.lambertw().div(negln); + let upper = negln.lambertw(false).div(negln); + let slogzero = Decimal.dOne; + if (range == 1) slogzero = lower.mul(upper).sqrt(); + else if (range == 2) slogzero = upper.mul(2); + let slogone = baseD.pow(slogzero); + let wholeheight = Math.floor(slogdest); + let fracheight = slogdest - wholeheight; + let towertop = slogzero.pow(1 - fracheight).mul(slogone.pow(fracheight)); + return Decimal.tetrate(baseD, wholeheight, towertop, linear); //wholediff is a whole number so this is safe even if it ends up calling iteratedlog + } + const slogthis = this.slog(base, 100, linear).toNumber(); const slogdest = slogthis + diff; if (slogdest >= 0) { return Decimal.tetrate(base, slogdest, Decimal.dOne, linear); } else if (!Number.isFinite(slogdest)) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } else if (slogdest >= -1) { return Decimal.log(Decimal.tetrate(base, slogdest + 1, Decimal.dOne, linear), base); } else { @@ -3631,28 +3724,163 @@ export default class Decimal { } } + //Apparently having something be private but not static breaks everything + /** + * A strange version of slog for bases between 1 and e^1/e which can handle values above base^^Infinity. + * Returns a pair of a Decimal and a number, with the number always being 0, 1, or 2. The number indicates what range we're in: + * 0 means we're below the lower solution of b^x = x, and so the normal slog is used. + * 1 means we're between the two solutions of b^x = x, with the geometric mean of the two solutions arbitrarily chosen to be the value with a slog of 0. + * 2 means we're above the upper solution of b^x = x, with (upper solution * 2) arbitrarily chosen to be the value with a slog of 0. + * + * The values returned by this function don't really have much mathematical meaning, but the difference between two values does. + * Therefore, this function is kept private, but it's used for layeradd on these small bases. + */ + private static excess_slog(value : DecimalSource, base : DecimalSource, linear = false) : [Decimal, 0 | 1 | 2] { + value = D(value); + base = D(base); + let baseD = base; + base = base.toNumber(); + if (base == 1 || base <= 0) return [FC_NN(Number.NaN, Number.NaN, Number.NaN), 0]; + if (base > 1.44466786100976613366) return [value.slog(base, 100, linear), 0]; + const negln = Decimal.ln(base).neg(); + let lower = negln.lambertw().div(negln); + let upper = Decimal.dInf; + if (base > 1) upper = negln.lambertw(false).div(negln); + if (base > 1.444667861009099) { + lower = upper = Decimal.fromNumber(Math.E); + } + if (value.lt(lower)) return [value.slog(base, 100, linear), 0]; + if (value.eq(lower)) return [FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY), 0]; + if (value.eq(upper)) return [FC_NN(1, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY), 2]; + if (value.gt(upper)) { + let slogzero = upper.mul(2); + let slogone = baseD.pow(slogzero); + let estimate = 0; + if (value.gte(slogzero) && value.lt(slogone)) estimate = 0; + else if (value.gte(slogone)) { + let payload = slogone; + estimate = 1; + while (payload.lt(value)) { + payload = baseD.pow(payload); + estimate = estimate + 1; + if (payload.layer > 3) { + let layersleft = Math.floor(value.layer - payload.layer + 1); + payload = baseD.iteratedexp(layersleft, payload, linear); + estimate = estimate + layersleft; + } + } + if (payload.gt(value)) { + payload = payload.log(base); + estimate = estimate - 1; + } + } + else if (value.lt(slogzero)) { + let payload = slogzero; + estimate = 0; + while (payload.gt(value)) { + payload = payload.log(base); + estimate = estimate - 1; + } + } + let fracheight = 0; + let tested = 0; + let step_size = 0.5; + let towertop = slogzero; + let guess : Decimal = Decimal.dZero; + while (step_size > 1e-16) { + tested = fracheight + step_size; + towertop = slogzero.pow(1 - tested).mul(slogone.pow(tested)) //Weighted geometric average + guess = Decimal.iteratedexp(base, estimate, towertop); + if (guess.eq(value)) return [new Decimal(estimate + tested), 2]; + else if (guess.lt(value)) fracheight += step_size; + step_size /= 2; + } + if (guess.neq_tolerance(value, 1e-7)) return [FC_NN(Number.NaN, Number.NaN, Number.NaN), 0]; + return [new Decimal(estimate + fracheight), 2]; + } + if (value.lt(upper) && value.gt(lower)) { + let slogzero = lower.mul(upper).sqrt(); //Geometric mean of the two b^x = x solutions + let slogone = baseD.pow(slogzero); + let estimate = 0; + if (value.lte(slogzero) && value.gt(slogone)) estimate = 0; + else if (value.lte(slogone)) { + let payload = slogone; + estimate = 1; + while (payload.gt(value)) { + payload = baseD.pow(payload); + estimate = estimate + 1; + } + if (payload.lt(value)) { + payload = payload.log(base); + estimate = estimate - 1; + } + } + else if (value.gt(slogzero)) { + let payload = slogzero; + estimate = 0; + while (payload.lt(value)) { + payload = payload.log(base); + estimate = estimate - 1; + } + } + let fracheight = 0; + let tested = 0; + let step_size = 0.5; + let towertop = slogzero; + let guess : Decimal = Decimal.dZero; + while (step_size > 1e-16) { + tested = fracheight + step_size; + towertop = slogzero.pow(1 - tested).mul(slogone.pow(tested)) //Weighted geometric average + guess = Decimal.iteratedexp(base, estimate, towertop); + if (guess.eq(value)) return [new Decimal(estimate + tested), 1]; + else if (guess.gt(value)) fracheight += step_size; + step_size /= 2; + } + if (guess.neq_tolerance(value, 1e-7)) return [FC_NN(Number.NaN, Number.NaN, Number.NaN), 0]; + return [new Decimal(estimate + fracheight), 1]; + } + throw new Error("Unhandled behavior in excess_slog"); + } + /** * The Lambert W function, also called the omega function or product logarithm, is the solution W(x) === x*e^x. - * https://en.wikipedia.org/wiki/Lambert_W_function + * https://en.wikipedia.org/wiki/Lambert_W_function + * + * This is a multi-valued function in the complex plane, but only two branches matter for real numbers: the "principal branch" W0, and the "non-principal branch" W_-1. + * W_0 works for any number >= -1/e, but W_-1 only works for nonpositive numbers >= -1/e. + * The "principal" parameter, which is true by default, decides which branch we're looking for: W_0 is used if principal is true, W_-1 is used if principal is false. */ //Some special values, for testing: https://en.wikipedia.org/wiki/Lambert_W_function#Special_values - public lambertw(): Decimal { + public lambertw(principal = true): Decimal { if (this.lt(-0.3678794411710499)) { - throw Error("lambertw is unimplemented for results less than -1, sorry!"); - } else if (this.mag < 0) { - return Decimal.fromNumber(f_lambertw(this.toNumber())); - } else if (this.layer === 0) { - return Decimal.fromNumber(f_lambertw(this.sign * this.mag)); - } else if (this.layer === 1) { - return d_lambertw(this); - } else if (this.layer === 2) { - return d_lambertw(this); + return FC_NN(Number.NaN, Number.NaN, Number.NaN); //complex + } + else if (principal) { + if (this.abs().lt("1e-300")) return new Decimal(this); + else if (this.mag < 0) { + return Decimal.fromNumber(f_lambertw(this.toNumber())); + } else if (this.layer === 0) { + return Decimal.fromNumber(f_lambertw(this.sign * this.mag)); + } else if (this.lt("eee15")) { + return d_lambertw(this); + } else { // Numbers this large would sometimes fail to converge using d_lambertw, and at this size this.ln() is close enough + return this.ln(); + } } - if (this.layer >= 3) { - return FC_NN(this.sign, this.layer - 1, this.mag); + else { + if (this.sign === 1) { + return FC_NN(Number.NaN, Number.NaN, Number.NaN); //complex + } + if (this.layer === 0) { + return Decimal.fromNumber(f_lambertw(this.sign * this.mag, 1e-10, false)); + } + else if (this.layer == 1) { + return d_lambertw(this, 1e-10, false); + } + else { + return this.neg().recip().lambertw().neg(); + } } - - throw "Unhandled behavior in lambertw()"; } /** @@ -3676,10 +3904,10 @@ export default class Decimal { return this; } if (this.eq(Decimal.dInf)) { - return Decimal.dInf; + return FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); } if (!this.isFinite()) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //Using linear approximation, x^^n = x^n if 0 < n < 1 if (degree > 0 && degree < 1) { @@ -3691,7 +3919,7 @@ export default class Decimal { } //Super roots with -1 <= degree < 0 have either no solution or infinitely many solutions, and tetration with height <= -2 returns NaN, so super roots of degree <= -2 don't work if (degree <= 0) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //Infinite degree super-root is x^(1/x) between 1/e <= x <= e, undefined otherwise if (degree == Number.POSITIVE_INFINITY) { @@ -3700,21 +3928,21 @@ export default class Decimal { return this.pow(this.recip()); } else { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } } //Special case: any super-root of 1 is 1 if (this.eq(1)) { - return Decimal.dOne; + return FC_NN(1, 0, 1); } //TODO: base < 0 (It'll probably be NaN anyway) if (this.lt(0)) { - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //Treat all numbers of layer <= -2 as zero, because they effectively are if (this.lte("1ee-16")) { - if (degree % 2 == 1) return this; - else return Decimal.dNaN; + if (degree % 2 == 1) return new Decimal(this); + else return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //this > 1 if (this.gt(1)) { @@ -3927,7 +4155,7 @@ export default class Decimal { else lower = guess; if (guess.eq(previous)) loopGoing = false; else previous = guess; - if (upper.gt("1e18")) return Decimal.dNaN; + if (upper.gt("1e18")) return FC_NN(Number.NaN, Number.NaN, Number.NaN); } //using guess.neq(minimum) led to imprecision errors, so here's a fixed version of that if (!(guess.eq_tolerance(minimum, 1e-15))) { @@ -3938,7 +4166,7 @@ export default class Decimal { //Check if the root is in the zero range. if (maximum.eq(FC(1, 10, 1))) { //There is no zero range, so the super root doesn't exist - return Decimal.dNaN; + return FC_NN(Number.NaN, Number.NaN, Number.NaN); } lower = FC(1, 10, 1); upper = maximum; @@ -3952,7 +4180,7 @@ export default class Decimal { else lower = guess; if (guess.eq(previous)) loopGoing = false; else previous = guess; - if (upper.gt("1e18")) return Decimal.dNaN; + if (upper.gt("1e18")) return FC_NN(Number.NaN, Number.NaN, Number.NaN); } return guess.pow10().recip(); } @@ -3971,7 +4199,7 @@ export default class Decimal { * For non-whole pentation heights, the linear approximation of pentation is always used, as there is no defined analytic approximation of pentation. */ public pentate(height = 2, payload: DecimalSource = FC_NN(1, 0, 1), linear = false): Decimal { - payload = D(payload); + payload = new Decimal(payload); const oldheight = height; height = Math.trunc(height); const fracheight = oldheight - height; @@ -4011,7 +4239,7 @@ export default class Decimal { */ public sin(): this | Decimal { if (this.mag < 0) { - return this; + return new Decimal(this); } if (this.layer === 0) { return Decimal.fromNumber(Math.sin(this.sign * this.mag)); @@ -4024,7 +4252,7 @@ export default class Decimal { */ public cos(): Decimal { if (this.mag < 0) { - return Decimal.dOne; + return FC_NN(1, 0, 1); } if (this.layer === 0) { return Decimal.fromNumber(Math.cos(this.sign * this.mag)); @@ -4037,7 +4265,7 @@ export default class Decimal { */ public tan(): this | Decimal { if (this.mag < 0) { - return this; + return new Decimal(this); } if (this.layer === 0) { return Decimal.fromNumber(Math.tan(this.sign * this.mag)); @@ -4050,7 +4278,7 @@ export default class Decimal { */ public asin(): this | Decimal { if (this.mag < 0) { - return this; + return new Decimal(this); } if (this.layer === 0) { return Decimal.fromNumber(Math.asin(this.sign * this.mag)); @@ -4076,7 +4304,7 @@ export default class Decimal { */ public atan(): this | Decimal { if (this.mag < 0) { - return this; + return new Decimal(this); } if (this.layer === 0) { return Decimal.fromNumber(Math.atan(this.sign * this.mag)); @@ -4135,7 +4363,7 @@ export default class Decimal { */ public ascensionPenalty(ascensions: DecimalSource): Decimal { if (ascensions === 0) { - return this; + return new Decimal(this); } return this.root(Decimal.pow(10, ascensions)); diff --git a/src/unit_tests.js b/src/unit_tests.js index 1ed9ee9..a5d980f 100644 --- a/src/unit_tests.js +++ b/src/unit_tests.js @@ -91,8 +91,8 @@ var test_tetrate_slog = function() let tower = Math.random()*10 - 1; let round_trip = new Decimal(base).tetrate(tower).slog(base).toNumber(); let round_trip_linear = new Decimal(base).tetrate(tower, 1, true).slog(base, 100, true).toNumber(); - assert_eq_tolerance("Test 1: " + base + ", " + tower, round_trip, tower, base < 2 ? 1e-2 : 1e-10); - assert_eq_tolerance("Test 2: " + base + ", " + tower, round_trip_linear, tower, 1e-10); + assert_eq_tolerance("Test 1: " + base + ", " + tower + ", analytic", round_trip, tower, base < 2 ? 1e-2 : 1e-10); + assert_eq_tolerance("Test 2: " + base + ", " + tower + ", linear", round_trip_linear, tower, 1e-10); } } @@ -105,7 +105,9 @@ var test_layeradd10_twice = function() var both = Math.random()*100; var expected = first+both+1; var result = new Decimal(10).layeradd10(first).layeradd10(both).slog(); - assert_eq_tolerance(first + ", " + both, expected, result); + var result_linear = new Decimal(10).layeradd10(first, true).layeradd10(both, true).slog(10, 100, true); + assert_eq_tolerance(first + ", " + both + ", analytic", expected, result); + assert_eq_tolerance(first + ", " + both + ", linear", expected, result_linear); } } @@ -119,7 +121,9 @@ var test_layeradd10_reverse = function() first += both; var expected = first-both+1; var result = new Decimal(10).layeradd10(first).layeradd10(-both).slog(); - assert_eq_tolerance(first + ", " + both, expected, result); + var result_linear = new Decimal(10).layeradd10(first, true).layeradd10(-both, true).slog(10, 100, true); + assert_eq_tolerance(first + ", " + both + ", analytic", expected, result); + assert_eq_tolerance(first + ", " + both + ", linear", expected, result_linear); } } @@ -133,7 +137,9 @@ var test_layeradd10_twice_anybase = function() var base = Math.random()*8+2; var expected = first+both+1; var result = new Decimal(base).layeradd(first, base).layeradd(both, base).slog(base); - assert_eq_tolerance(first + ", " + both + ", " + base, expected, result); + var result_linear = new Decimal(base).layeradd(first, base, true).layeradd(both, base, true).slog(base, 100, true); + assert_eq_tolerance(first + ", " + both + ", " + base + ", analytic", expected, result); + assert_eq_tolerance(first + ", " + both + ", " + base + ", linear", expected, result_linear); } } @@ -148,7 +154,9 @@ var test_layeradd10_reverse_anybase = function() first += both; var expected = first-both+1; var result = new Decimal(base).layeradd(first, base).layeradd(-both, base).slog(base); - assert_eq_tolerance(first + ", " + both + ", " + base, expected, result); + var result_linear = new Decimal(base).layeradd(first, base, true).layeradd(-both, base, true).slog(base, 100, true); + assert_eq_tolerance(first + ", " + both + ", " + base + ", analytic", expected, result); + assert_eq_tolerance(first + ", " + both + ", " + base + ", linear", expected, result_linear); } } @@ -161,7 +169,10 @@ var test_tetrate_iteratedlog = function() var both = Math.round((Math.random()*30))/10; var tetrateonly = Decimal.tetrate(10, first); var tetrateandlog = Decimal.tetrate(10, first+both).iteratedlog(10, both); - assert_eq_tolerance(first + ", " + both, tetrateonly, tetrateandlog); + var tetrateonly_linear = Decimal.tetrate(10, first, 1, true); + var tetrateandlog_linear = Decimal.tetrate(10, first+both, 1, true).iteratedlog(10, both, true); + assert_eq_tolerance(first + ", " + both + ", analytic", tetrateonly, tetrateandlog); + assert_eq_tolerance(first + ", " + both + ", linear", tetrateonly_linear, tetrateandlog_linear); } } @@ -172,10 +183,14 @@ var test_tetrate_base = function() { var first = Math.round((Math.random()*30))/10; var both = Math.round((Math.random()*30))/10; - var base = Math.random()*8+2; + var base = Math.random()*9+1; + if (base == 1) base = 2; var tetrateonly = Decimal.tetrate(base, first); var tetrateandlog = Decimal.tetrate(base, first+both).iteratedlog(base, both); - assert_eq_tolerance(first + ", " + both + ", " + base, tetrateonly, tetrateandlog); + var tetrateonly_linear = Decimal.tetrate(base, first, 1, true); + var tetrateandlog_linear = Decimal.tetrate(base, first+both, 1, true).iteratedlog(base, both, true); + assert_eq_tolerance(first + ", " + both + ", " + base + ", analytic: " + tetrateonly + ", " + tetrateandlog, tetrateonly, tetrateandlog); + assert_eq_tolerance(first + ", " + both + ", " + base + ", linear: " + tetrateonly_linear + ", " + tetrateandlog_linear, tetrateonly_linear, tetrateandlog_linear); } } @@ -186,10 +201,14 @@ var test_tetrate_base_2 = function() { var first = Math.round((Math.random()*30))/10; var both = Math.round((Math.random()*30))/10; - var base = Math.random()*8+2; + var base = Math.random()*9+1; + if (base == 1) base = 2; var tetrateonly = Decimal.tetrate(base, first, base); var tetrateandlog = Decimal.tetrate(base, first+both, base).iteratedlog(base, both); - assert_eq_tolerance(first + ", " + both + ", " + base, tetrateonly, tetrateandlog); + var tetrateonly_linear = Decimal.tetrate(base, first, base, true); + var tetrateandlog_linear = Decimal.tetrate(base, first+both, base, true).iteratedlog(base, both, true); + assert_eq_tolerance(first + ", " + both + ", " + base + ", analytic", tetrateonly, tetrateandlog); + assert_eq_tolerance(first + ", " + both + ", " + base + ", linear", tetrateonly_linear, tetrateandlog_linear); } } @@ -215,6 +234,17 @@ var test_lambertw_2 = function() } } +var test_lambertw_3 = function() +{ + console.log("test_lambertw_3") + for (var i = 0; i < 1000; ++i) + { + var xex = Decimal.iteratedexp(10, 3, new Decimal(Math.random() * 16)); + var x = Decimal.lambertw(xex); + assert_eq_tolerance(xex, xex, x.mul(Decimal.exp(x))); + } +} + var test_add_number = function() { console.log("test_add_number") @@ -257,6 +287,7 @@ var test_pow_root = function() { var a = Decimal.randomDecimalForTesting(Math.round(Math.random()*4)); var b = Decimal.randomDecimalForTesting(Math.round(Math.random()*4)); + if (b.eq(0)) continue; if (Math.random() > 0.5 && a.sign !== 0) { a = a.recip(); } if (Math.random() > 0.5 && b.sign !== 0) { b = b.recip(); } var c = a.pow(b); @@ -319,13 +350,36 @@ var test_modulo = function() { var test_tetrate_linear_sroot = function() { console.log("test_tetrate_linear_sroot"); + let base = Decimal.dOne; + let degree = Decimal.dOne; for (var i = 0; i < 1000; ++i) { - let base = Decimal.dOne; - let degree = Decimal.dOne; try { base = Decimal.randomDecimalForTesting(Math.round(Math.random()*4)); if (base.lt(0)) base = base.neg(); + if (base.lt(1)) base = base.recip(); + degree = Math.random()*10; + if (base.eq(0)) base = Decimal.dOne; + let round_trip = new Decimal(base).linear_sroot(degree).tetrate(degree, 1, true); + assert_eq_tolerance(base + ", " + degree + " -> " + round_trip, round_trip, base); + } + catch (err) { + console.log("Error in " + base + ", " + degree + ": " + err); + } + } +} + +var test_tetrate_linear_sroot_lt1 = function() +{ + console.log("test_tetrate_linear_sroot_lt1"); + let base = Decimal.dOne; + let degree = Decimal.dOne; + for (var i = 0; i < 100; ++i) + { + try { + base = Decimal.randomDecimalForTesting(2); + if (base.lt(0)) base = base.neg(); + if (base.gt(1)) base = base.recip(); degree = Math.random()*10; if (base.eq(0)) base = Decimal.dOne; let round_trip = new Decimal(base).linear_sroot(degree).tetrate(degree, 1, true); @@ -365,6 +419,114 @@ var test_ssqrt = function() } } +var test_lambertw_nonPrincipal = function() +{ + console.log("test_lambertw_nonPrincipal") + for (var i = 0; i < 1000; ++i) + { + var xex = new Decimal(Math.random()*-0.3678794411710499); + var x = Decimal.lambertw(xex, false); + assert_eq_tolerance(xex, xex, x.mul(Decimal.exp(x))); + } +} + +var test_lambertw_nonPrincipal_2 = function() +{ + console.log("test_lambertw_nonPrincipal_2") + for (var i = 0; i < 1000; ++i) + { + var xex = new Decimal(Math.exp(Math.random()*-100 - 1)).neg(); + var x = Decimal.lambertw(xex, false); + assert_eq_tolerance(xex, xex, x.mul(Decimal.exp(x))); + } +} + +var test_lambertw_nonPrincipal_3 = function() +{ + console.log("test_lambertw_nonPrincipal_3") + for (var i = 0; i < 1000; ++i) + { + var xex = Decimal.iteratedexp(10, 3, new Decimal(Math.random() * 16)).neg().recip(); + var x = Decimal.lambertw(xex, false); + assert_eq_tolerance(xex, xex, x.mul(Decimal.exp(x))); + } +} + +var test_tetrate_small_bases = function() +{ + console.log("test_tetrate_small_bases") + for (var i = 0; i < 1000; ++i) + { + var base = 1.44466786100976613366 - Math.random(); + var negln = Decimal.ln(base).neg(); + var lower = negln.lambertw().div(negln); + var upper = Decimal.dInf; + var payload = Decimal.pow10(Math.random() * 6 - 3); + if (base > 1) upper = negln.lambertw(false).div(negln); + var finite = Decimal.tetrate(base, 20000 + Math.random(), payload); + var infinite = Decimal.tetrate(base, Infinity, payload); + var finite_linear = Decimal.tetrate(base, 20000 + Math.random(), payload, true); + if (payload.gt(upper)) { + if (finite.lt("F10000") || infinite.lt("F10000") || finite_linear.lt("F10000")) console.log(base + " " + payload); + } + else if (payload.eq(upper)) { + assert_eq_tolerance(base + ", " + payload + ", finite", finite, upper); + assert_eq_tolerance(base + ", " + payload + ", infinite", infinite, upper); + assert_eq_tolerance(base + ", " + payload + ", finite linear", finite_linear, upper); + } + else { + assert_eq_tolerance(base + ", " + payload + ", finite", finite, lower); + assert_eq_tolerance(base + ", " + payload + ", infinite", infinite, lower); + assert_eq_tolerance(base + ", " + payload + ", finite linear", finite_linear, lower); + } + } +} + +var test_layeradd_recursive_property = function() { + console.log("test_layeradd_recursive_property") + for (var i = 0; i < 1000; ++i) + { + var base = 1 + Math.random() * 20; + var payload = new Decimal(Math.random() * 100); + assert_eq_tolerance(base + ", " + payload + ", analytic", payload.layeradd(1, base), Decimal.pow(base, payload)); + assert_eq_tolerance(base + ", " + payload + ", linear", payload.layeradd(1, base, true), Decimal.pow(base, payload)); + } +} + +var test_tetrate_increasing = function() { + console.log("test_tetrate_increasing") + OuterLoop : for (var i = 0; i < 100; ++i) + { + var base = 1 + Math.random() * 5; + var payload = new Decimal(Math.random() * 100); + var height = Math.random() * 4 - 1; + var nextheight = height + Math.random(); + var linear = (Math.random() > 0.5); + var lowertetrate = Decimal.tetrate(base, height, payload, linear); + var highertetrate = Decimal.tetrate(base, nextheight, payload, linear); + var lower = Decimal.dInf; + var upper = Decimal.dInf; + if (base < 1.44466786100976613366) { + var negln = Decimal.ln(base).neg(); + lower = negln.lambertw().div(negln); + if (base > 1) upper = negln.lambertw(false).div(negln); + } + if (payload.eq(lower) || payload.eq(upper)) continue; + var decreasing = payload.gt(lower) && payload.lt(upper); + for (var j = 0; j < 5; j++) { + if ((!decreasing && highertetrate.lt(lowertetrate)) || (decreasing && highertetrate.gt(lowertetrate))) { + console.log(base + ", " + payload + ((linear) ? "linear" : "analytic")); + continue OuterLoop; + } + height = nextheight; + nextheight = height + Math.random(); + linear = (Math.random() > 0.5) + lowertetrate = Decimal.tetrate(base, height, payload, linear); + highertetrate = Decimal.tetrate(base, nextheight, payload, linear); + } + } +} + var all_tests = function() { test_tetrate_ground_truth(); @@ -379,11 +541,19 @@ var all_tests = function() test_tetrate_base_2(); test_lambertw(); test_lambertw_2(); + test_lambertw_3(); test_add_number(); test_mul(); test_pow_root(); test_tetrate_linear_truth(); test_modulo(); test_tetrate_linear_sroot(); + test_tetrate_linear_sroot_lt1(); test_ssqrt(); + test_lambertw_nonPrincipal(); + test_lambertw_nonPrincipal_2(); + test_lambertw_nonPrincipal_3(); + test_tetrate_small_bases(); + test_layeradd_recursive_property(); + test_tetrate_increasing(); } \ No newline at end of file