diff --git a/README.md b/README.md index 9545eda..b64a7e5 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ A Javascript numerical library to represent numbers as large as 10^^1e308 and as 'small' as 10^-(10^^1e308). This is a sequel to break_infinity.js, my other library which maxes out at 1e1e308 ( https://github.com/Patashu/break_infinity.js ) and its C# port ( https://github.com/Razenpok/BreakInfinity.cs ). Despite handling a wider range of numbers, execution time is comparable (within 2x/0.5x as fast as break_infinity.js in testing) and it has the same interface, so it can be used as a drop-in replacement for break_infinity.js and decimal.js. -Now with arbitrary real height and base handling in your favourite hyper 4 operators (tetrate, iterated exponentiation, iterated logarithm, super logarithm, super square root) and even in pentate (if you want to do that for some reason)! Using the linear approximation. (Analytical approximation is too hard for me atm.) +Now with arbitrary real height and base handling in your favourite hyper 4 operators (tetrate, iterated exponentiation, iterated logarithm, super logarithm, super root) and even in pentate (if you want to do that for some reason)! Using the linear approximation. (Analytical approximation is too hard for me atm.) The internal representation is as follows: `Decimal.fromComponents(sign, layer, mag)` === `sign*10^10^10^ ... (layer times) mag`. So a layer 0 number is just `sign*mag`, a layer 1 number is `sign*10^mag`, a layer 2 number is `sign*10^10^mag`, and so on. If `layer > 0` and `mag < 0`, then the number's exponent is negative, e.g. `sign*10^-10^10^10^ ... mag`. @@ -14,7 +14,7 @@ Create a Decimal with `new Decimal(String or Number or Decimal)` or with `Decima IMPORTANT NOTE TO PEOPLE CONVERTING FROM break_infinity.js: log/log2/log10/ln now return Decimal not Number! You'll also need to reconsider your string parsing/displaying functions and consider moving e/exponent calls to absLog10. Support for very small numbers has finally been added, so things like tickspeed multiplier being 1e-400 will be fine now! -Functions you can call include `abs, neg, round, floor, ceil, trunc, add, sub, mul, div, recip, cmp, cmpabs, max, min, maxabs, minabs, log, log10, ln, pow, root, factorial, gamma, exp, sqrt, tetrate, iteratedexp, iteratedlog, layeradd10, layeradd, slog, ssqrt, lambertw, pentate` and more! Javascript operators like `+` and `*` do not work - you need to call the equivalent functions instead. +Functions you can call include `abs, neg, round, floor, ceil, trunc, add, sub, mul, div, recip, mod, cmp, cmpabs, max, min, maxabs, minabs, log, log10, ln, pow, root, factorial, gamma, exp, sqrt, tetrate, iteratedexp, iteratedlog, layeradd10, layeradd, slog, ssqrt, lambertw, linear_sroot, pentate` and more! Javascript operators like `+` and `*` do not work - you need to call the equivalent functions instead. Accepted input formats to new Decimal or Decimal.fromString: @@ -33,6 +33,7 @@ eeee... (N es) X === 10^10^10^ ... (N 10^s) X N PT X === 10^10^10^ ... (N 10^s) X N PT (X) === 10^10^10^ ... (N 10^s) X NpX === 10^10^10^ ... (N 10^s) X +XFN === 10^10^10^ ... (N 10^s) X X^Y === X^Y X^^N === X^X^X^ ... (N X^s) 1 X^^N;Y === X^X^X^ ... (N X^s) Y diff --git a/break_eternity.cjs.js b/break_eternity.cjs.js index c5ebca4..e301df3 100644 --- a/break_eternity.cjs.js +++ b/break_eternity.cjs.js @@ -5,17 +5,15 @@ function _classCallCheck(instance, Constructor) { throw new TypeError("Cannot call a class as a function"); } } - function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, descriptor.key, descriptor); + Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } - function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); @@ -24,6 +22,20 @@ function _createClass(Constructor, protoProps, staticProps) { }); return Constructor; } +function _toPrimitive(input, hint) { + if (typeof input !== "object" || input === null) return input; + var prim = input[Symbol.toPrimitive]; + if (prim !== undefined) { + var res = prim.call(input, hint || "default"); + if (typeof res !== "object") return res; + throw new TypeError("@@toPrimitive must return a primitive value."); + } + return (hint === "string" ? String : Number)(input); +} +function _toPropertyKey(arg) { + var key = _toPrimitive(arg, "string"); + return typeof key === "symbol" ? key : String(key); +} /** * A LRU cache intended for caching pure functions. @@ -39,18 +51,16 @@ var LRUCache = /*#__PURE__*/function () { */ function LRUCache(maxSize) { _classCallCheck(this, LRUCache); - - this.map = new Map(); // Invariant: Exactly one of the below is true before and after calling a + this.map = new Map(); + // Invariant: Exactly one of the below is true before and after calling a // LRUCache method: // - first and last are both undefined, and map.size() is 0. // - first and last are the same object, and map.size() is 1. // - first and last are different objects, and map.size() is greater than 1. - this.first = undefined; this.last = undefined; this.maxSize = maxSize; } - _createClass(LRUCache, [{ key: "size", get: function get() { @@ -62,53 +72,48 @@ var LRUCache = /*#__PURE__*/function () { * @param key The key to get. * @returns The cached value, or undefined if key is not in the cache. */ - }, { key: "get", value: function get(key) { var node = this.map.get(key); - if (node === undefined) { return undefined; - } // It is guaranteed that there is at least one item in the cache. + } + // It is guaranteed that there is at least one item in the cache. // Therefore, first and last are guaranteed to be a ListNode... // but if there is only one item, they might be the same. // Update the order of the list to make this node the first node in the // list. // This isn't needed if this node is already the first node in the list. - - if (node !== this.first) { // As this node is DIFFERENT from the first node, it is guaranteed that // there are at least two items in the cache. // However, this node could possibly be the last item. if (node === this.last) { // This node IS the last node. - this.last = node.prev; // From the invariants, there must be at least two items in the cache, + this.last = node.prev; + // From the invariants, there must be at least two items in the cache, // so node - which is the original "last node" - must have a defined // previous node. Therefore, this.last - set above - must be defined // here. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.last.next = undefined; } else { // This node is somewhere in the middle of the list, so there must be at // least THREE items in the list, and this node's prev and next must be // defined here. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - node.prev.next = node.next; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - + node.prev.next = node.next; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion node.next.prev = node.prev; } - - node.next = this.first; // From the invariants, there must be at least two items in the cache, so + node.next = this.first; + // From the invariants, there must be at least two items in the cache, so // this.first must be a valid ListNode. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.first.prev = node; this.first = node; } - return node.value; } /** @@ -118,7 +123,6 @@ var LRUCache = /*#__PURE__*/function () { * @param value The value of the entry. * @throws Error, if the map already contains the key. */ - }, { key: "set", value: function set(key, value) { @@ -126,13 +130,11 @@ var LRUCache = /*#__PURE__*/function () { if (this.maxSize < 1) { return; } - if (this.map.has(key)) { throw new Error("Cannot update existing keys in the cache"); } - - var node = new ListNode(key, value); // Move node to the front of the list. - + var node = new ListNode(key, value); + // Move node to the front of the list. if (this.first === undefined) { // If the first is undefined, the last is undefined too. // Therefore, this cache has no items in it. @@ -144,9 +146,7 @@ var LRUCache = /*#__PURE__*/function () { this.first.prev = node; this.first = node; } - this.map.set(key, node); - while (this.map.size > this.maxSize) { // We are guaranteed that this.maxSize >= 1, // so this.map.size is guaranteed to be >= 2, @@ -155,22 +155,19 @@ var LRUCache = /*#__PURE__*/function () { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion var last = this.last; this.map["delete"](last.key); - this.last = last.prev; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - + this.last = last.prev; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion this.last.next = undefined; } } }]); - return LRUCache; }(); /** * A node in a doubly linked list. */ - var ListNode = /*#__PURE__*/_createClass(function ListNode(key, value) { _classCallCheck(this, ListNode); - this.next = undefined; this.prev = undefined; this.key = key; @@ -178,112 +175,110 @@ var ListNode = /*#__PURE__*/_createClass(function ListNode(key, value) { }); var MAX_SIGNIFICANT_DIGITS = 17; //Maximum number of digits of precision to assume in Number - var EXP_LIMIT = 9e15; //If we're ABOVE this value, increase a layer. (9e15 is close to the largest integer that can fit in a Number.) - var LAYER_DOWN = Math.log10(9e15); var FIRST_NEG_LAYER = 1 / 9e15; //At layer 0, smaller non-zero numbers than this become layer 1 numbers with negative mag. After that the pattern continues as normal. - var NUMBER_EXP_MAX = 308; //The largest exponent that can appear in a Number, though not all mantissas are valid here. - var NUMBER_EXP_MIN = -324; //The smallest exponent that can appear in a Number, though not all mantissas are valid here. - var MAX_ES_IN_A_ROW = 5; //For default toString behaviour, when to swap from eee... to (e^n) syntax. - var DEFAULT_FROM_STRING_CACHE_SIZE = (1 << 10) - 1; // The default size of the LRU cache used to cache Decimal.fromString. - var powerOf10 = function () { // We need this lookup table because Math.pow(10, exponent) // when exponent's absolute value is large is slightly inaccurate. // You can fix it with the power of math... or just make a lookup table. // Faster AND simpler var powersOf10 = []; - for (var i = NUMBER_EXP_MIN + 1; i <= NUMBER_EXP_MAX; i++) { powersOf10.push(Number("1e" + i)); } - var indexOf0InPowersOf10 = 323; return function (power) { return powersOf10[power + indexOf0InPowersOf10]; }; -}(); //tetration/slog to real height stuff +}(); +//tetration/slog to real height stuff //background info and tables of values for critical functions taken here: https://github.com/Patashu/break_eternity.js/issues/22 - - var critical_headers = [2, Math.E, 3, 4, 5, 6, 7, 8, 9, 10]; -var critical_tetr_values = [[// Base 2 (using http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html ) -1, 1.0891180521811202527, 1.1789767925673958433, 1.2701455431742086633, 1.3632090180450091941, 1.4587818160364217007, 1.5575237916251418333, 1.6601571006859253673, 1.7674858188369780435, 1.8804192098842727359, 2], [// Base E (using http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html ) +var critical_tetr_values = [[ +// Base 2 (using http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html ) +1, 1.0891180521811202527, 1.1789767925673958433, 1.2701455431742086633, 1.3632090180450091941, 1.4587818160364217007, 1.5575237916251418333, 1.6601571006859253673, 1.7674858188369780435, 1.8804192098842727359, 2], [ +// Base E (using http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html ) 1, 1.1121114330934078681, 1.2310389249316089299, 1.3583836963111376089, 1.4960519303993531879, 1.6463542337511945810, 1.8121385357018724464, 1.9969713246183068478, 2.2053895545527544330, 2.4432574483385252544, Math.E //1.0 -], [// Base 3 -1, 1.1187738849693603, 1.2464963939368214, 1.38527004705667, 1.5376664685821402, 1.7068895236551784, 1.897001227148399, 2.1132403089001035, 2.362480153784171, 2.6539010333870774, 3], [// Base 4 -1, 1.1367350847096405, 1.2889510672956703, 1.4606478703324786, 1.6570295196661111, 1.8850062585672889, 2.1539465047453485, 2.476829779693097, 2.872061932789197, 3.3664204535587183, 4], [// Base 5 -1, 1.1494592900767588, 1.319708228183931, 1.5166291280087583, 1.748171114438024, 2.0253263297298045, 2.3636668498288547, 2.7858359149579424, 3.3257226212448145, 4.035730287722532, 5], [// Base 6 -1, 1.159225940787673, 1.343712473580932, 1.5611293155111927, 1.8221199554561318, 2.14183924486326, 2.542468319282638, 3.0574682501653316, 3.7390572020926873, 4.6719550537360774, 6], [// Base 7 -1, 1.1670905356972596, 1.3632807444991446, 1.5979222279405536, 1.8842640123816674, 2.2416069644878687, 2.69893426559423, 3.3012632110403577, 4.121250340630164, 5.281493033448316, 7], [// Base 8 -1, 1.1736630594087796, 1.379783782386201, 1.6292821855668218, 1.9378971836180754, 2.3289975651071977, 2.8384347394720835, 3.5232708454565906, 4.478242031114584, 5.868592169644505, 8], [// Base 9 -1, 1.1793017514670474, 1.394054150657457, 1.65664127441059, 1.985170999970283, 2.4069682290577457, 2.9647310119960752, 3.7278665320924946, 4.814462547283592, 6.436522247411611, 9], [// Base 10 (using http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html ) +], [ +// Base 3 +1, 1.1187738849693603, 1.2464963939368214, 1.38527004705667, 1.5376664685821402, 1.7068895236551784, 1.897001227148399, 2.1132403089001035, 2.362480153784171, 2.6539010333870774, 3], [ +// Base 4 +1, 1.1367350847096405, 1.2889510672956703, 1.4606478703324786, 1.6570295196661111, 1.8850062585672889, 2.1539465047453485, 2.476829779693097, 2.872061932789197, 3.3664204535587183, 4], [ +// Base 5 +1, 1.1494592900767588, 1.319708228183931, 1.5166291280087583, 1.748171114438024, 2.0253263297298045, 2.3636668498288547, 2.7858359149579424, 3.3257226212448145, 4.035730287722532, 5], [ +// Base 6 +1, 1.159225940787673, 1.343712473580932, 1.5611293155111927, 1.8221199554561318, 2.14183924486326, 2.542468319282638, 3.0574682501653316, 3.7390572020926873, 4.6719550537360774, 6], [ +// Base 7 +1, 1.1670905356972596, 1.3632807444991446, 1.5979222279405536, 1.8842640123816674, 2.2416069644878687, 2.69893426559423, 3.3012632110403577, 4.121250340630164, 5.281493033448316, 7], [ +// Base 8 +1, 1.1736630594087796, 1.379783782386201, 1.6292821855668218, 1.9378971836180754, 2.3289975651071977, 2.8384347394720835, 3.5232708454565906, 4.478242031114584, 5.868592169644505, 8], [ +// Base 9 +1, 1.1793017514670474, 1.394054150657457, 1.65664127441059, 1.985170999970283, 2.4069682290577457, 2.9647310119960752, 3.7278665320924946, 4.814462547283592, 6.436522247411611, 9], [ +// Base 10 (using http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html ) 1, 1.1840100246247336579, 1.4061375836156954169, 1.6802272208863963918, 2.026757028388618927, 2.4770056063449647580, 3.0805252717554819987, 3.9191964192627283911, 5.1351528408331864230, 6.9899611795347148455, 10]]; -var critical_slog_values = [[// Base 2 --1, -0.9194161097107025, -0.8335625019330468, -0.7425599821143978, -0.6466611521029437, -0.5462617907227869, -0.4419033816638769, -0.3342645487554494, -0.224140440909962, -0.11241087890006762, 0], [// Base E +var critical_slog_values = [[ +// Base 2 +-1, -0.9194161097107025, -0.8335625019330468, -0.7425599821143978, -0.6466611521029437, -0.5462617907227869, -0.4419033816638769, -0.3342645487554494, -0.224140440909962, -0.11241087890006762, 0], [ +// Base E -1, -0.90603157029014, -0.80786507256596, -0.7064666939634, -0.60294836853664, -0.49849837513117, -0.39430303318768, -0.29147201034755, -0.19097820800866, -0.09361896280296, 0 //1.0 -], [// Base 3 --1, -0.9021579584316141, -0.8005762598234203, -0.6964780623319391, -0.5911906810998454, -0.486050182576545, -0.3823089430815083, -0.28106046722897615, -0.1831906535795894, -0.08935809204418144, 0], [// Base 4 --1, -0.8917227442365535, -0.781258746326964, -0.6705130326902455, -0.5612813129406509, -0.4551067709033134, -0.35319256652135966, -0.2563741554088552, -0.1651412821106526, -0.0796919581982668, 0], [// Base 5 --1, -0.8843387974366064, -0.7678744063886243, -0.6529563724510552, -0.5415870994657841, -0.4352842206588936, -0.33504449124791424, -0.24138853420685147, -0.15445285440944467, -0.07409659641336663, 0], [// Base 6 --1, -0.8786709358426346, -0.7577735191184886, -0.6399546189952064, -0.527284921869926, -0.4211627631006314, -0.3223479611761232, -0.23107655627789858, -0.1472057700818259, -0.07035171210706326, 0], [// Base 7 --1, -0.8740862815291583, -0.7497032990976209, -0.6297119746181752, -0.5161838335958787, -0.41036238255751956, -0.31277212146489963, -0.2233976621705518, -0.1418697367979619, -0.06762117662323441, 0], [// Base 8 --1, -0.8702632331800649, -0.7430366914122081, -0.6213373075161548, -0.5072025698095242, -0.40171437727184167, -0.30517930701410456, -0.21736343968190863, -0.137710238299109, -0.06550774483471955, 0], [// Base 9 --1, -0.8670016295947213, -0.7373984232432306, -0.6143173985094293, -0.49973884395492807, -0.394584953527678, -0.2989649949848695, -0.21245647317021688, -0.13434688362382652, -0.0638072667348083, 0], [// Base 10 +], [ +// Base 3 +-1, -0.9021579584316141, -0.8005762598234203, -0.6964780623319391, -0.5911906810998454, -0.486050182576545, -0.3823089430815083, -0.28106046722897615, -0.1831906535795894, -0.08935809204418144, 0], [ +// Base 4 +-1, -0.8917227442365535, -0.781258746326964, -0.6705130326902455, -0.5612813129406509, -0.4551067709033134, -0.35319256652135966, -0.2563741554088552, -0.1651412821106526, -0.0796919581982668, 0], [ +// Base 5 +-1, -0.8843387974366064, -0.7678744063886243, -0.6529563724510552, -0.5415870994657841, -0.4352842206588936, -0.33504449124791424, -0.24138853420685147, -0.15445285440944467, -0.07409659641336663, 0], [ +// Base 6 +-1, -0.8786709358426346, -0.7577735191184886, -0.6399546189952064, -0.527284921869926, -0.4211627631006314, -0.3223479611761232, -0.23107655627789858, -0.1472057700818259, -0.07035171210706326, 0], [ +// Base 7 +-1, -0.8740862815291583, -0.7497032990976209, -0.6297119746181752, -0.5161838335958787, -0.41036238255751956, -0.31277212146489963, -0.2233976621705518, -0.1418697367979619, -0.06762117662323441, 0], [ +// Base 8 +-1, -0.8702632331800649, -0.7430366914122081, -0.6213373075161548, -0.5072025698095242, -0.40171437727184167, -0.30517930701410456, -0.21736343968190863, -0.137710238299109, -0.06550774483471955, 0], [ +// Base 9 +-1, -0.8670016295947213, -0.7373984232432306, -0.6143173985094293, -0.49973884395492807, -0.394584953527678, -0.2989649949848695, -0.21245647317021688, -0.13434688362382652, -0.0638072667348083, 0], [ +// Base 10 -1, -0.8641642839543857, -0.732534623168535, -0.6083127477059322, -0.4934049257184696, -0.3885773075899922, -0.29376029055315767, -0.2083678561173622, -0.13155653399373268, -0.062401588652553186, 0]]; - var D = function D(value) { return Decimal.fromValue_noAlloc(value); }; - var FC = function FC(sign, layer, mag) { return Decimal.fromComponents(sign, layer, mag); }; - var FC_NN = function FC_NN(sign, layer, mag) { return Decimal.fromComponents_noNormalize(sign, layer, mag); -}; // eslint-disable-next-line @typescript-eslint/no-unused-vars - +}; var decimalPlaces = function decimalPlaces(value, places) { var len = places + 1; var numDigits = Math.ceil(Math.log10(Math.abs(value))); var rounded = Math.round(value * Math.pow(10, len - numDigits)) * Math.pow(10, numDigits - len); return parseFloat(rounded.toFixed(Math.max(len - numDigits, 0))); }; - var f_maglog10 = function f_maglog10(n) { return Math.sign(n) * Math.log10(Math.abs(n)); -}; //from HyperCalc source code - - +}; +//from HyperCalc source code var f_gamma = function f_gamma(n) { if (!isFinite(n)) { return n; } - if (n < -50) { if (n === Math.trunc(n)) { return Number.NEGATIVE_INFINITY; } - return 0; } - var scal1 = 1; - while (n < 10) { scal1 = scal1 * n; ++n; } - n -= 1; var l = 0.9189385332046727; //0.5*Math.log(2*Math.PI) - l = l + (n + 0.5) * Math.log(n); l = l - n; var n2 = n * n; @@ -305,99 +300,82 @@ var f_gamma = function f_gamma(n) { 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 - var f_lambertw = function f_lambertw(z) { var tol = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1e-10; 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; } 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); - if (Math.abs(wn - w) < tol * Math.abs(wn)) { return wn; } else { w = wn; } } - - throw Error("Iteration failed to converge: ".concat(z.toString())); //return Number.NaN; -}; //from https://github.com/scipy/scipy/blob/8dba340293fe20e62e173bdf2c10ae208286692f/scipy/special/lambertw.pxd + throw Error("Iteration failed to converge: ".concat(z.toString())); + //return Number.NaN; +}; +//from https://github.com/scipy/scipy/blob/8dba340293fe20e62e173bdf2c10ae208286692f/scipy/special/lambertw.pxd // 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) { var tol = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1e-10; var w; var ew, wewz, wn; - if (!Number.isFinite(z.mag)) { return z; } - if (z.eq(Decimal.dZero)) { return z; } - 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); //Halley's method; see 5.9 in [1] - + } + //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(); wewz = w.sub(z.mul(ew)); wn = w.sub(wewz.div(w.add(1).sub(w.add(2).mul(wewz).div(Decimal.mul(2, w).add(2))))); - if (Decimal.abs(wn.sub(w)).lt(Decimal.abs(wn).mul(tol))) { return wn; } else { w = wn; } } - - throw Error("Iteration failed to converge: ".concat(z.toString())); //return Decimal.dNaN; + throw Error("Iteration failed to converge: ".concat(z.toString())); + //return Decimal.dNaN; } /** - * The Decimal's value is simply mantissa * 10^exponent. + * The value of the Decimal is sign * 10^10^10...^mag, with (layer) 10s. If the layer is not 0, then negative mag means it's the reciprocal of the corresponding number with positive mag. */ - - var Decimal = /*#__PURE__*/function () { function Decimal(value) { _classCallCheck(this, Decimal); - this.sign = 0; this.mag = 0; this.layer = 0; - if (value instanceof Decimal) { this.fromDecimal(value); } else if (typeof value === "number") { @@ -406,23 +384,20 @@ var Decimal = /*#__PURE__*/function () { this.fromString(value); } } - _createClass(Decimal, [{ key: "m", get: function get() { if (this.sign === 0) { return 0; } else if (this.layer === 0) { - var exp = Math.floor(Math.log10(this.mag)); //handle special case 5e-324 - + var exp = Math.floor(Math.log10(this.mag)); + //handle special case 5e-324 var man; - if (this.mag === 5e-324) { man = 5; } else { man = this.mag / powerOf10(exp); } - return this.sign * man; } else if (this.layer === 1) { var residue = this.mag - Math.floor(this.mag); @@ -438,7 +413,6 @@ var Decimal = /*#__PURE__*/function () { } else { //don't even pretend mantissa is meaningful this.sign = Math.sign(value); - if (this.sign === 0) { this.layer = 0; this.exponent = 0; @@ -476,8 +450,8 @@ var Decimal = /*#__PURE__*/function () { } else { this.sign = value; } - } // Object.defineProperty(Decimal.prototype, "mantissa", { - + } + // Object.defineProperty(Decimal.prototype, "mantissa", { }, { key: "mantissa", get: function get() { @@ -516,23 +490,19 @@ var Decimal = /*#__PURE__*/function () { this.layer = 0; return this; } - if (this.layer === 0 && this.mag < 0) { //extract sign from negative mag at layer 0 this.mag = -this.mag; this.sign = -this.sign; - } //Handle shifting from layer 0 to negative layers. - - + } + //Handle shifting from layer 0 to negative layers. if (this.layer === 0 && this.mag < FIRST_NEG_LAYER) { this.layer += 1; this.mag = Math.log10(this.mag); return this; } - var absmag = Math.abs(this.mag); var signmag = Math.sign(this.mag); - if (absmag >= EXP_LIMIT) { this.layer += 1; this.mag = signmag * Math.log10(absmag); @@ -540,7 +510,6 @@ var Decimal = /*#__PURE__*/function () { } else { while (absmag < LAYER_DOWN && this.layer > 0) { this.layer -= 1; - if (this.layer === 0) { this.mag = Math.pow(10, this.mag); } else { @@ -549,7 +518,6 @@ var Decimal = /*#__PURE__*/function () { signmag = Math.sign(this.mag); } } - if (this.layer === 0) { if (this.mag < 0) { //extract sign from negative mag at layer 0 @@ -561,7 +529,6 @@ var Decimal = /*#__PURE__*/function () { } } } - return this; } }, { @@ -620,215 +587,181 @@ var Decimal = /*#__PURE__*/function () { value: function fromString(value) { var originalValue = value; var cached = Decimal.fromStringCache.get(originalValue); - if (cached !== undefined) { return this.fromDecimal(cached); } - { value = value.replace(",", ""); - } //Handle x^^^y format. - - + } + //Handle x^^^y format. var pentationparts = value.split("^^^"); - if (pentationparts.length === 2) { var _base = parseFloat(pentationparts[0]); - var _height = parseFloat(pentationparts[1]); - var heightparts = pentationparts[1].split(";"); var payload = 1; - if (heightparts.length === 2) { payload = parseFloat(heightparts[1]); - if (!isFinite(payload)) { payload = 1; } } - if (isFinite(_base) && isFinite(_height)) { var result = Decimal.pentate(_base, _height, payload); this.sign = result.sign; this.layer = result.layer; this.mag = result.mag; - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } - } //Handle x^^y format. - - + } + //Handle x^^y format. var tetrationparts = value.split("^^"); - if (tetrationparts.length === 2) { var _base2 = parseFloat(tetrationparts[0]); - var _height2 = parseFloat(tetrationparts[1]); - var _heightparts = tetrationparts[1].split(";"); - var _payload = 1; - if (_heightparts.length === 2) { _payload = parseFloat(_heightparts[1]); - if (!isFinite(_payload)) { _payload = 1; } } - if (isFinite(_base2) && isFinite(_height2)) { var _result = Decimal.tetrate(_base2, _height2, _payload); - this.sign = _result.sign; this.layer = _result.layer; this.mag = _result.mag; - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } - } //Handle x^y format. - - + } + //Handle x^y format. var powparts = value.split("^"); - if (powparts.length === 2) { var _base3 = parseFloat(powparts[0]); - var _exponent = parseFloat(powparts[1]); - if (isFinite(_base3) && isFinite(_exponent)) { var _result2 = Decimal.pow(_base3, _exponent); - this.sign = _result2.sign; this.layer = _result2.layer; this.mag = _result2.mag; - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } - } //Handle various cases involving it being a Big Number. - - - value = value.trim().toLowerCase(); //handle X PT Y format. - + } + //Handle various cases involving it being a Big Number. + value = value.trim().toLowerCase(); + //handle X PT Y format. var base; var height; var ptparts = value.split("pt"); - if (ptparts.length === 2) { base = 10; height = parseFloat(ptparts[0]); ptparts[1] = ptparts[1].replace("(", ""); ptparts[1] = ptparts[1].replace(")", ""); - var _payload2 = parseFloat(ptparts[1]); - if (!isFinite(_payload2)) { _payload2 = 1; } - if (isFinite(base) && isFinite(height)) { var _result3 = Decimal.tetrate(base, height, _payload2); - this.sign = _result3.sign; this.layer = _result3.layer; this.mag = _result3.mag; - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } - } //handle XpY format (it's the same thing just with p). - - + } + //handle XpY format (it's the same thing just with p). ptparts = value.split("p"); - if (ptparts.length === 2) { base = 10; height = parseFloat(ptparts[0]); ptparts[1] = ptparts[1].replace("(", ""); ptparts[1] = ptparts[1].replace(")", ""); - var _payload3 = parseFloat(ptparts[1]); - if (!isFinite(_payload3)) { _payload3 = 1; } - if (isFinite(base) && isFinite(height)) { var _result4 = Decimal.tetrate(base, height, _payload3); - this.sign = _result4.sign; this.layer = _result4.layer; this.mag = _result4.mag; - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } } - + //handle XFY format + ptparts = value.split("f"); + if (ptparts.length === 2) { + base = 10; + ptparts[0] = ptparts[0].replace("(", ""); + ptparts[0] = ptparts[0].replace(")", ""); + var _payload4 = parseFloat(ptparts[0]); + ptparts[1] = ptparts[1].replace("(", ""); + ptparts[1] = ptparts[1].replace(")", ""); + height = parseFloat(ptparts[1]); + if (!isFinite(_payload4)) { + _payload4 = 1; + } + if (isFinite(base) && isFinite(height)) { + var _result5 = Decimal.tetrate(base, height, _payload4); + this.sign = _result5.sign; + this.layer = _result5.layer; + this.mag = _result5.mag; + if (Decimal.fromStringCache.maxSize >= 1) { + Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); + } + return this; + } + } var parts = value.split("e"); - var ecount = parts.length - 1; //Handle numbers that are exactly floats (0 or 1 es). - + var ecount = parts.length - 1; + //Handle numbers that are exactly floats (0 or 1 es). if (ecount === 0) { var numberAttempt = parseFloat(value); - if (isFinite(numberAttempt)) { this.fromNumber(numberAttempt); - if (Decimal.fromStringCache.size >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } } else if (ecount === 1) { //Very small numbers ("2e-3000" and so on) may look like valid floats but round to 0. var _numberAttempt = parseFloat(value); - if (isFinite(_numberAttempt) && _numberAttempt !== 0) { this.fromNumber(_numberAttempt); - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } - } //Handle new (e^N)X format. - - + } + //Handle new (e^N)X format. var newparts = value.split("e^"); - if (newparts.length === 2) { this.sign = 1; - if (newparts[0].charAt(0) == "-") { this.sign = -1; } - var layerstring = ""; - for (var i = 0; i < newparts[1].length; ++i) { var chrcode = newparts[1].charCodeAt(i); - if (chrcode >= 43 && chrcode <= 57 || chrcode === 101) { //is "0" to "9" or "+" or "-" or "." or "e" (or "," or "/") layerstring += newparts[1].charAt(i); @@ -837,93 +770,76 @@ var Decimal = /*#__PURE__*/function () { this.layer = parseFloat(layerstring); this.mag = parseFloat(newparts[1].substr(i + 1)); this.normalize(); - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } } } - if (ecount < 1) { this.sign = 0; this.layer = 0; this.mag = 0; - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } - var mantissa = parseFloat(parts[0]); - if (mantissa === 0) { this.sign = 0; this.layer = 0; this.mag = 0; - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } - - var exponent = parseFloat(parts[parts.length - 1]); //handle numbers like AeBeC and AeeeeBeC - + var exponent = parseFloat(parts[parts.length - 1]); + //handle numbers like AeBeC and AeeeeBeC if (ecount >= 2) { var me = parseFloat(parts[parts.length - 2]); - if (isFinite(me)) { exponent *= Math.sign(me); exponent += f_maglog10(me); } - } //Handle numbers written like eee... (N es) X - - + } + //Handle numbers written like eee... (N es) X if (!isFinite(mantissa)) { this.sign = parts[0] === "-" ? -1 : 1; this.layer = ecount; this.mag = exponent; - } //Handle numbers written like XeY + } + //Handle numbers written like XeY else if (ecount === 1) { this.sign = Math.sign(mantissa); - this.layer = 1; //Example: 2e10 is equal to 10^log10(2e10) which is equal to 10^(10+log10(2)) - + this.layer = 1; + //Example: 2e10 is equal to 10^log10(2e10) which is equal to 10^(10+log10(2)) this.mag = exponent + Math.log10(Math.abs(mantissa)); - } //Handle numbers written like Xeee... (N es) Y + } + //Handle numbers written like Xeee... (N es) Y else { this.sign = Math.sign(mantissa); this.layer = ecount; - if (ecount === 2) { - var _result5 = Decimal.mul(FC(1, 2, exponent), D(mantissa)); - - this.sign = _result5.sign; - this.layer = _result5.layer; - this.mag = _result5.mag; - + var _result6 = Decimal.mul(FC(1, 2, exponent), D(mantissa)); + this.sign = _result6.sign; + this.layer = _result6.layer; + this.mag = _result6.mag; if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } else { //at eee and above, mantissa is too small to be recognizable! this.mag = exponent; } } - this.normalize(); - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } }, { @@ -932,15 +848,12 @@ var Decimal = /*#__PURE__*/function () { if (value instanceof Decimal) { return this.fromDecimal(value); } - if (typeof value === "number") { return this.fromNumber(value); } - if (typeof value === "string") { return this.fromString(value); } - this.sign = 0; this.layer = 0; this.mag = 0; @@ -952,7 +865,6 @@ var Decimal = /*#__PURE__*/function () { if (!Number.isFinite(this.layer)) { return Number.NaN; } - if (this.layer === 0) { return this.sign * this.mag; } else if (this.layer === 1) { @@ -969,11 +881,9 @@ var Decimal = /*#__PURE__*/function () { if (isNaN(this.m)) { return Number.NaN; } - if (this.m === 0) { return 0; } - return decimalPlaces(this.m, places); } }, { @@ -983,11 +893,9 @@ var Decimal = /*#__PURE__*/function () { if (isNaN(this.mag)) { return Number.NaN; } - if (this.mag === 0) { return 0; } - return decimalPlaces(this.mag, places); } }, { @@ -996,16 +904,13 @@ 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) { return this.sign === 1 ? "Infinity" : "-Infinity"; } - if (this.layer === 0) { if (this.mag < 1e21 && this.mag > 1e-7 || this.mag === 0) { return (this.sign * this.mag).toString(); } - return this.m + "e" + this.e; } else if (this.layer === 1) { return this.m + "e" + this.e; @@ -1024,7 +929,6 @@ var Decimal = /*#__PURE__*/function () { if (this.layer === 0) { return (this.sign * this.mag).toExponential(places); } - return this.toStringWithDecimalPlaces(places); } }, { @@ -1033,7 +937,6 @@ var Decimal = /*#__PURE__*/function () { if (this.layer === 0) { return (this.sign * this.mag).toFixed(places); } - return this.toStringWithDecimalPlaces(places); } }, { @@ -1042,11 +945,9 @@ var Decimal = /*#__PURE__*/function () { if (this.e <= -7) { return this.toExponential(places - 1); } - if (places > this.e) { return this.toFixed(places - this.exponent - 1); } - return this.toExponential(places - 1); } }, { @@ -1066,7 +967,6 @@ var Decimal = /*#__PURE__*/function () { if (this.mag < 1e21 && this.mag > 1e-7 || this.mag === 0) { return (this.sign * this.mag).toFixed(places); } - return decimalPlaces(this.m, places) + "e" + decimalPlaces(this.e, places); } else if (this.layer === 1) { return decimalPlaces(this.m, places) + "e" + decimalPlaces(this.e, places); @@ -1098,10 +998,10 @@ var Decimal = /*#__PURE__*/function () { key: "negated", value: function negated() { return this.neg(); - } // public sign () { + } + // public sign () { // return this.sign; // } - }, { key: "sgn", value: function sgn() { @@ -1113,11 +1013,9 @@ var Decimal = /*#__PURE__*/function () { if (this.mag < 0) { return Decimal.dZero; } - if (this.layer === 0) { return FC(this.sign, 0, Math.round(this.mag)); } - return this; } }, { @@ -1126,11 +1024,9 @@ var Decimal = /*#__PURE__*/function () { if (this.mag < 0) { return Decimal.dZero; } - if (this.layer === 0) { return FC(this.sign, 0, Math.floor(this.mag)); } - return this; } }, { @@ -1139,11 +1035,9 @@ var Decimal = /*#__PURE__*/function () { if (this.mag < 0) { return Decimal.dZero; } - if (this.layer === 0) { return FC(this.sign, 0, Math.ceil(this.mag)); } - return this; } }, { @@ -1152,47 +1046,39 @@ var Decimal = /*#__PURE__*/function () { if (this.mag < 0) { return Decimal.dZero; } - if (this.layer === 0) { return FC(this.sign, 0, Math.trunc(this.mag)); } - return this; } }, { key: "add", value: function add(value) { - var decimal = D(value); //inf/nan check - + var decimal = D(value); + //inf/nan check if (!Number.isFinite(this.layer)) { return this; } - if (!Number.isFinite(decimal.layer)) { return decimal; - } //Special case - if one of the numbers is 0, return the other number. - - + } + //Special case - if one of the numbers is 0, return the other number. if (this.sign === 0) { return decimal; } - if (decimal.sign === 0) { return this; - } //Special case - Adding a number to its negation produces 0, no matter how large. - - + } + //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) { return FC_NN(0, 0, 0); } - var a; - var b; //Special case: If one of the numbers is layer 2 or higher, just take the bigger number. - + var b; + //Special case: If one of the numbers is layer 2 or higher, just take the bigger number. if (this.layer >= 2 || decimal.layer >= 2) { return this.maxabs(decimal); } - if (Decimal.cmpabs(this, decimal) > 0) { a = this; b = decimal; @@ -1200,18 +1086,15 @@ var Decimal = /*#__PURE__*/function () { a = decimal; b = this; } - if (a.layer === 0 && b.layer === 0) { return Decimal.fromNumber(a.sign * a.mag + b.sign * b.mag); } - var layera = a.layer * Math.sign(a.mag); - var layerb = b.layer * Math.sign(b.mag); //If one of the numbers is 2+ layers higher than the other, just take the bigger number. - + var layerb = b.layer * Math.sign(b.mag); + //If one of the numbers is 2+ layers higher than the other, just take the bigger number. if (layera - layerb >= 2) { return a; } - if (layera === 0 && layerb === -1) { if (Math.abs(b.mag - Math.log10(a.mag)) > MAX_SIGNIFICANT_DIGITS) { return a; @@ -1221,26 +1104,20 @@ var Decimal = /*#__PURE__*/function () { return FC(Math.sign(mantissa), 1, b.mag + Math.log10(Math.abs(mantissa))); } } - if (layera === 1 && layerb === 0) { if (Math.abs(a.mag - Math.log10(b.mag)) > MAX_SIGNIFICANT_DIGITS) { return a; } else { var _magdiff = Math.pow(10, a.mag - Math.log10(b.mag)); - var _mantissa = b.sign + a.sign * _magdiff; - return FC(Math.sign(_mantissa), 1, Math.log10(b.mag) + Math.log10(Math.abs(_mantissa))); } } - if (Math.abs(a.mag - b.mag) > MAX_SIGNIFICANT_DIGITS) { return a; } else { var _magdiff2 = Math.pow(10, a.mag - b.mag); - var _mantissa2 = b.sign + a.sign * _magdiff2; - return FC(Math.sign(_mantissa2), 1, b.mag + Math.log10(Math.abs(_mantissa2))); } } @@ -1267,29 +1144,25 @@ var Decimal = /*#__PURE__*/function () { }, { key: "mul", value: function mul(value) { - var decimal = D(value); //inf/nan check - + var decimal = D(value); + //inf/nan check if (!Number.isFinite(this.layer)) { return this; } - if (!Number.isFinite(decimal.layer)) { return decimal; - } //Special case - if one of the numbers is 0, return 0. - - + } + //Special case - if one of the numbers is 0, return 0. if (this.sign === 0 || decimal.sign === 0) { return FC_NN(0, 0, 0); - } //Special case - Multiplying a number by its own reciprocal yields +/- 1, no matter how large. - - + } + //Special case - Multiplying a number by its own reciprocal yields +/- 1, no matter how large. if (this.layer === decimal.layer && this.mag === -decimal.mag) { return FC_NN(this.sign * decimal.sign, 0, 1); } - var a; - var b; //Which number is bigger in terms of its multiplicative distance from 1? - + 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; @@ -1297,35 +1170,27 @@ var Decimal = /*#__PURE__*/function () { a = decimal; b = this; } - if (a.layer === 0 && b.layer === 0) { return Decimal.fromNumber(a.sign * b.sign * a.mag * b.mag); - } //Special case: If one of the numbers is layer 3 or higher or one of the numbers is 2+ layers bigger than the other, just take the bigger number. - - + } + //Special case: If one of the numbers is layer 3 or higher or one of the numbers is 2+ layers bigger than the other, just take the bigger number. if (a.layer >= 3 || a.layer - b.layer >= 2) { return FC(a.sign * b.sign, a.layer, a.mag); } - if (a.layer === 1 && b.layer === 0) { return FC(a.sign * b.sign, 1, a.mag + Math.log10(b.mag)); } - if (a.layer === 1 && b.layer === 1) { return FC(a.sign * b.sign, 1, a.mag + b.mag); } - if (a.layer === 2 && b.layer === 1) { var newmag = FC(Math.sign(a.mag), a.layer - 1, Math.abs(a.mag)).add(FC(Math.sign(b.mag), b.layer - 1, Math.abs(b.mag))); return FC(a.sign * b.sign, newmag.layer + 1, newmag.sign * newmag.mag); } - if (a.layer === 2 && b.layer === 2) { var _newmag = FC(Math.sign(a.mag), a.layer - 1, Math.abs(a.mag)).add(FC(Math.sign(b.mag), b.layer - 1, Math.abs(b.mag))); - return FC(a.sign * b.sign, _newmag.layer + 1, _newmag.sign * _newmag.mag); } - throw Error("Bad arguments to mul: " + this + ", " + value); } }, { @@ -1380,23 +1245,53 @@ var Decimal = /*#__PURE__*/function () { value: function reciprocate() { return this.recip(); } + //Taken from OmegaNum.js, with a couple touch-ups + //"Truncated division" modulo, like JavaScript's % + }, { + key: "mod", + value: function mod(value) { + var decimal = D(value).abs(); + if (decimal.eq(Decimal.dZero)) return Decimal.dZero; + 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 + if (isFinite(num_this) && isFinite(num_decimal) && num_this != 0 && num_decimal != 0) { + return new Decimal(num_this % num_decimal); + } + if (this.sub(decimal).eq(this)) { + //decimal is too small to register to this + return Decimal.dZero; + } + if (decimal.sub(this).eq(decimal)) { + //this is too small to register to decimal + return this; + } + if (this.sign == -1) return this.abs().mod(decimal).neg(); + return this.sub(this.div(decimal).floor().mul(decimal)); + } + }, { + key: "modulo", + value: function modulo(value) { + return this.mod(value); + } + }, { + key: "modular", + value: function modular(value) { + return this.mod(value); + } /** * -1 for less than value, 0 for equals value, 1 for greater than value */ - }, { key: "cmp", value: function cmp(value) { var decimal = D(value); - if (this.sign > decimal.sign) { return 1; } - if (this.sign < decimal.sign) { return -1; } - return this.sign * this.cmpabs(value); } }, { @@ -1405,23 +1300,18 @@ var Decimal = /*#__PURE__*/function () { var decimal = D(value); var layera = this.mag > 0 ? this.layer : -this.layer; var layerb = decimal.mag > 0 ? decimal.layer : -decimal.layer; - if (layera > layerb) { return 1; } - if (layera < layerb) { return -1; } - if (this.mag > decimal.mag) { return 1; } - if (this.mag < decimal.mag) { return -1; } - return 0; } }, { @@ -1440,11 +1330,9 @@ var Decimal = /*#__PURE__*/function () { function isFinite() { return _isFinite2.apply(this, arguments); } - isFinite.toString = function () { return _isFinite2.toString(); }; - return isFinite; }(function () { return isFinite(this.sign) && isFinite(this.layer) && isFinite(this.mag); @@ -1545,37 +1433,29 @@ var Decimal = /*#__PURE__*/function () { * For example, if you put in 1e-9, then any number closer to the * larger number than (larger number)*1e-9 will be considered equal. */ - }, { key: "eq_tolerance", value: function eq_tolerance(value, tolerance) { var decimal = D(value); // https://stackoverflow.com/a/33024979 - if (tolerance == null) { tolerance = 1e-7; - } //Numbers that are too far away are never close. - - + } + //Numbers that are too far away are never close. if (this.sign !== decimal.sign) { return false; } - if (Math.abs(this.layer - decimal.layer) > 1) { return false; - } // return abs(a-b) <= tolerance * max(abs(a), abs(b)) - - + } + // return abs(a-b) <= tolerance * max(abs(a), abs(b)) var magA = this.mag; var magB = decimal.mag; - if (this.layer > decimal.layer) { magB = f_maglog10(magB); } - if (this.layer < decimal.layer) { magA = f_maglog10(magA); } - return Math.abs(magA - magB) <= tolerance * Math.max(Math.abs(magA), Math.abs(magB)); } }, { @@ -1623,7 +1503,6 @@ var Decimal = /*#__PURE__*/function () { if (this.lt(Decimal.dZero)) { return Decimal.dZero; } - return this.log10(); } }, { @@ -1652,21 +1531,17 @@ var Decimal = /*#__PURE__*/function () { key: "log", value: function log(base) { base = D(base); - if (this.sign <= 0) { return Decimal.dNaN; } - if (base.sign <= 0) { return Decimal.dNaN; } - if (base.sign === 1 && base.layer === 0 && base.mag === 1) { return Decimal.dNaN; } else if (this.layer === 0 && base.layer === 0) { return FC(this.sign, 0, Math.log(this.mag) / Math.log(base.mag)); } - return Decimal.div(this.log10(), base.log10()); } }, { @@ -1709,39 +1584,32 @@ var Decimal = /*#__PURE__*/function () { value: function pow(value) { var decimal = D(value); var a = this; - var b = decimal; //special case: if a is 0, then return 0 (UNLESS b is 0, then return 1) - + var b = 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; - } //special case: if a is 1, then return 1 - - + } + //special case: if a is 1, then return 1 if (a.sign === 1 && a.layer === 0 && a.mag === 1) { return a; - } //special case: if b is 0, then return 1 - - + } + //special case: if b is 0, then return 1 if (b.sign === 0) { return FC_NN(1, 0, 1); - } //special case: if b is 1, then return a - - + } + //special case: if b is 1, then return a if (b.sign === 1 && b.layer === 0 && b.mag === 1) { return a; } - var result = a.absLog10().mul(b).pow10(); - if (this.sign === -1) { if (Math.abs(b.toNumber() % 2) % 2 === 1) { return result.neg(); } else if (Math.abs(b.toNumber() % 2) % 2 === 0) { return result; } - return Decimal.dNaN; } - return result; } }, { @@ -1756,13 +1624,11 @@ var Decimal = /*#__PURE__*/function () { */ if (!Number.isFinite(this.layer) || !Number.isFinite(this.mag)) { return Decimal.dNaN; - } - - var a = this; //handle layer 0 case - if no precision is lost just use Math.pow, else promote one layer - + } + var a = 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); - if (Number.isFinite(newmag) && Math.abs(newmag) >= 0.1) { return FC(1, 0, newmag); } else { @@ -1772,18 +1638,15 @@ var Decimal = /*#__PURE__*/function () { a = FC_NN(a.sign, a.layer + 1, Math.log10(a.mag)); } } - } //handle all 4 layer 1+ cases individually - - + } + //handle all 4 layer 1+ cases individually if (a.sign > 0 && a.mag >= 0) { return FC(a.sign, a.layer + 1, a.mag); } - if (a.sign < 0 && a.mag >= 0) { return FC(-a.sign, a.layer + 1, -a.mag); - } //both the negative mag cases are identical: one +/- rounding error - - + } + //both the negative mag cases are identical: one +/- rounding error return Decimal.dOne; } }, { @@ -1809,8 +1672,8 @@ var Decimal = /*#__PURE__*/function () { } else { return Decimal.exp(this); } - } //from HyperCalc source code - + } + //from HyperCalc source code }, { key: "gamma", value: function gamma() { @@ -1820,10 +1683,8 @@ var Decimal = /*#__PURE__*/function () { if (this.lt(FC_NN(1, 0, 24))) { return Decimal.fromNumber(f_gamma(this.sign * this.mag)); } - var t = this.mag - 1; var l = 0.9189385332046727; //0.5*Math.log(2*Math.PI) - l = l + (t + 0.5) * Math.log(t); l = l - t; var n2 = t * t; @@ -1831,21 +1692,17 @@ var Decimal = /*#__PURE__*/function () { var lm = 12 * np; var adj = 1 / lm; var l2 = l + adj; - if (l2 === l) { return Decimal.exp(l); } - l = l2; np = np * n2; lm = 360 * np; adj = 1 / lm; l2 = l - adj; - if (l2 === l) { return Decimal.exp(l); } - l = l2; np = np * n2; lm = 1260 * np; @@ -1873,7 +1730,6 @@ var Decimal = /*#__PURE__*/function () { if (this.mag < 0) { return Decimal.dOne; } - if (this.layer === 0 && this.mag <= 709.7) { return Decimal.fromNumber(Math.exp(this.sign * this.mag)); } else if (this.layer === 0) { @@ -1912,46 +1768,41 @@ var Decimal = /*#__PURE__*/function () { key: "cbrt", value: function cbrt() { return this.pow(1 / 3); - } //Tetration/tetrate: The result of exponentiating 'this' to 'this' 'height' times in a row. https://en.wikipedia.org/wiki/Tetration + } + //Tetration/tetrate: The result of exponentiating 'this' to 'this' 'height' times in a row. https://en.wikipedia.org/wiki/Tetration //If payload != 1, then this is 'iterated exponentiation', the result of exping (payload) to base (this) (height) times. https://andydude.github.io/tetration/archives/tetration2/ident.html //Works with negative and positive real heights. - }, { key: "tetrate", value: function tetrate() { 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; //x^^1 == x if (height === 1) { return Decimal.pow(this, payload); - } //x^^0 == 1 - - + } + //x^^0 == 1 if (height === 0) { return new Decimal(payload); - } //1^^x == 1 - - + } + //1^^x == 1 if (this.eq(Decimal.dOne)) { return Decimal.dOne; - } //-1^^x == -1 - - + } + //-1^^x == -1 if (this.eq(-1)) { return Decimal.pow(this, payload); } - if (height === Number.POSITIVE_INFINITY) { - var this_num = this.toNumber(); //within the convergence range? - + var this_num = this.toNumber(); + //within the convergence range? if (this_num <= 1.44466786100976613366 && this_num >= 0.06598803584531253708) { //hotfix for the very edge of the number range not being handled properly if (this_num > 1.444667861009099) { return Decimal.fromNumber(Math.E); - } //Formula for infinite height power tower. - - + } + //Formula for infinite height power tower. var negln = Decimal.ln(this).neg(); return negln.lambertw().div(negln); } else if (this_num > 1.44466786100976613366) { @@ -1963,259 +1814,232 @@ var Decimal = /*#__PURE__*/function () { //this_num < 0: quickly becomes a complex number return Decimal.dNaN; } - } //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 + } + //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 //using the linear approximation for height (TODO: don't know a better way to calculate it ATM, but it wouldn't surprise me if it's just NaN) - - if (this.eq(Decimal.dZero)) { var result = Math.abs((height + 1) % 2); - if (result > 1) { result = 2 - result; } - return Decimal.fromNumber(result); } - if (height < 0) { - return Decimal.iteratedlog(payload, this, -height); + return Decimal.iteratedlog(payload, this, -height, linear); } - payload = D(payload); var oldheight = height; height = Math.trunc(height); var fracheight = oldheight - height; - - if (this.gt(Decimal.dZero) && this.lte(1.44466786100976613366)) { + 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) { var old_payload = payload; - payload = this.pow(payload); //stop early if we converge - + payload = this.pow(payload); + //stop early if we converge if (old_payload.eq(payload)) { return payload; } } - - if (fracheight != 0) { + if (fracheight != 0 || oldheight > 10000) { var next_payload = this.pow(payload); - return payload.mul(1 - fracheight).add(next_payload.mul(fracheight)); + 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)); + } } - return payload; - } //TODO: base < 0, but it's hard for me to reason about (probably all non-integer heights are NaN automatically?) - - + } + //TODO: base < 0, but it's hard for me to reason about (probably all non-integer heights are NaN automatically?) if (fracheight !== 0) { if (payload.eq(Decimal.dOne)) { + //If (linear), use linear approximation even for bases <= 10 //TODO: for bases above 10, revert to old linear approximation until I can think of something better - if (this.gt(10)) { + if (this.gt(10) || linear) { payload = this.pow(fracheight); } else { - payload = Decimal.fromNumber(Decimal.tetrate_critical(this.toNumber(), fracheight)); //TODO: until the critical section grid can handle numbers below 2, scale them to the base + payload = Decimal.fromNumber(Decimal.tetrate_critical(this.toNumber(), fracheight)); + //TODO: until the critical section grid can handle numbers below 2, scale them to the base //TODO: maybe once the critical section grid has very large bases, this math can be appropriate for them too? I'll think about it - if (this.lt(2)) { payload = payload.sub(1).mul(this.minus(1)).plus(1); } } } else { if (this.eq(10)) { - payload = payload.layeradd10(fracheight); + payload = payload.layeradd10(fracheight, linear); } else { - payload = payload.layeradd(fracheight, this); + payload = payload.layeradd(fracheight, this, linear); } } } - for (var _i = 0; _i < height; ++_i) { - payload = this.pow(payload); //bail if we're NaN - + payload = this.pow(payload); + //bail if we're NaN if (!isFinite(payload.layer) || !isFinite(payload.mag)) { return payload.normalize(); - } //shortcut - - + } + //shortcut if (payload.layer - this.layer > 3) { return FC_NN(payload.sign, payload.layer + (height - _i - 1), payload.mag); - } //give up after 10000 iterations if nothing is happening - - + } + //give up after 10000 iterations if nothing is happening if (_i > 10000) { return payload; } } - return payload; - } //iteratedexp/iterated exponentiation: - all cases handled in tetrate, so just call it - + } + //iteratedexp/iterated exponentiation: - all cases handled in tetrate, so just call it }, { key: "iteratedexp", value: function iteratedexp() { 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); - return this.tetrate(height, payload); - } //iterated log/repeated log: The result of applying log(base) 'times' times in a row. Approximately equal to subtracting (times) from the number's slog representation. Equivalent to tetrating to a negative height. + var linear = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + return this.tetrate(height, payload, linear); + } + //iterated log/repeated log: The result of applying log(base) 'times' times in a row. Approximately equal to subtracting (times) from the number's slog representation. Equivalent to tetrating to a negative height. //Works with negative and positive real heights. - }, { key: "iteratedlog", value: function iteratedlog() { var base = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 10; var times = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; - + var linear = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; if (times < 0) { - return Decimal.tetrate(base, -times, this); + return Decimal.tetrate(base, -times, this, linear); } - base = D(base); var result = Decimal.fromDecimal(this); var fulltimes = times; times = Math.trunc(times); var fraction = fulltimes - times; - if (result.layer - base.layer > 3) { var layerloss = Math.min(times, result.layer - base.layer - 3); times -= layerloss; result.layer -= layerloss; } - for (var i = 0; i < times; ++i) { - result = result.log(base); //bail if we're NaN - + result = result.log(base); + //bail if we're NaN if (!isFinite(result.layer) || !isFinite(result.mag)) { return result.normalize(); - } //give up after 10000 iterations if nothing is happening - - + } + //give up after 10000 iterations if nothing is happening if (i > 10000) { return result; } - } //handle fractional part - - + } + //handle fractional part if (fraction > 0 && fraction < 1) { if (base.eq(10)) { - result = result.layeradd10(-fraction); + result = result.layeradd10(-fraction, linear); } else { - result = result.layeradd(-fraction, base); + result = result.layeradd(-fraction, base, linear); } } - return result; - } //Super-logarithm, one of tetration's inverses, tells you what size power tower you'd have to tetrate base to to get number. By definition, will never be higher than 1.8e308 in break_eternity.js, since a power tower 1.8e308 numbers tall is the largest representable number. + } + //Super-logarithm, one of tetration's inverses, tells you what size power tower you'd have to tetrate base to to get number. By definition, will never be higher than 1.8e308 in break_eternity.js, since a power tower 1.8e308 numbers tall is the largest representable number. // https://en.wikipedia.org/wiki/Super-logarithm // NEW: Accept a number of iterations, and use binary search to, after making an initial guess, hone in on the true value, assuming tetration as the ground truth. - }, { key: "slog", value: function slog() { var base = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 10; var iterations = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100; + var linear = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; var step_size = 0.001; var has_changed_directions_once = false; var previously_rose = false; - var result = this.slog_internal(base).toNumber(); - + var result = this.slog_internal(base, linear).toNumber(); for (var i = 1; i < iterations; ++i) { - var new_decimal = new Decimal(base).tetrate(result); + var new_decimal = new Decimal(base).tetrate(result, Decimal.dOne, linear); var currently_rose = new_decimal.gt(this); - if (i > 1) { if (previously_rose != currently_rose) { has_changed_directions_once = true; } } - previously_rose = currently_rose; - if (has_changed_directions_once) { step_size /= 2; } else { step_size *= 2; } - step_size = Math.abs(step_size) * (currently_rose ? -1 : 1); result += step_size; - if (step_size === 0) { break; } } - return Decimal.fromNumber(result); } }, { key: "slog_internal", value: function slog_internal() { var base = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 10; - base = D(base); //special cases: + var linear = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + base = D(base); + //special cases: //slog base 0 or lower is NaN - if (base.lte(Decimal.dZero)) { return Decimal.dNaN; - } //slog base 1 is NaN - - + } + //slog base 1 is NaN if (base.eq(Decimal.dOne)) { return Decimal.dNaN; - } //need to handle these small, wobbling bases specially - - + } + //need to handle these small, wobbling bases specially if (base.lt(Decimal.dOne)) { if (this.eq(Decimal.dOne)) { return Decimal.dZero; } - if (this.eq(Decimal.dZero)) { return Decimal.dNegOne; - } //0 < this < 1: ambiguous (happens multiple times) + } + //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; - } //slog_n(0) is -1 - - + } + //slog_n(0) is -1 if (this.mag < 0 || this.eq(Decimal.dZero)) { return Decimal.dNegOne; } - var result = 0; var copy = Decimal.fromDecimal(this); - if (copy.layer - base.layer > 3) { var layerloss = copy.layer - base.layer - 3; result += layerloss; copy.layer -= layerloss; } - for (var i = 0; i < 100; ++i) { if (copy.lt(Decimal.dZero)) { copy = Decimal.pow(base, copy); result -= 1; } else if (copy.lte(Decimal.dOne)) { - return Decimal.fromNumber(result + Decimal.slog_critical(base.toNumber(), copy.toNumber())); + if (linear) return Decimal.fromNumber(result + copy.toNumber() - 1);else return Decimal.fromNumber(result + Decimal.slog_critical(base.toNumber(), copy.toNumber())); } else { result += 1; copy = Decimal.log(copy, base); } } - return Decimal.fromNumber(result); - } //background info and tables of values for critical functions taken here: https://github.com/Patashu/break_eternity.js/issues/22 - + } + //background info and tables of values for critical functions taken here: https://github.com/Patashu/break_eternity.js/issues/22 }, { key: "layeradd10", - value: //Function for adding/removing layers from a Decimal, even fractional layers (e.g. its slog10 representation). + value: + //Function for adding/removing layers from a Decimal, even fractional layers (e.g. its slog10 representation). //Moved this over to use the same critical section as tetrate/slog. function layeradd10(diff) { + var linear = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; diff = Decimal.fromValue_noAlloc(diff).toNumber(); var result = Decimal.fromDecimal(this); - if (diff >= 1) { //bug fix: if result is very smol (mag < 0, layer > 0) turn it into 0 first if (result.mag < 0 && result.layer > 0) { @@ -2227,87 +2051,75 @@ var Decimal = /*#__PURE__*/function () { result.sign = 1; result.mag = -result.mag; } - var layeradd = Math.trunc(diff); diff -= layeradd; result.layer += layeradd; } - if (diff <= -1) { var _layeradd = Math.trunc(diff); - diff -= _layeradd; result.layer += _layeradd; - if (result.layer < 0) { for (var i = 0; i < 100; ++i) { result.layer++; result.mag = Math.log10(result.mag); - if (!isFinite(result.mag)) { //another bugfix: if we hit -Infinity mag, then we should return negative infinity, not 0. 0.layeradd10(-1) h its this if (result.sign === 0) { result.sign = 1; - } //also this, for 0.layeradd10(-2) - - + } + //also this, for 0.layeradd10(-2) if (result.layer < 0) { result.layer = 0; } - return result.normalize(); } - if (result.layer >= 0) { break; } } } } - while (result.layer < 0) { result.layer++; result.mag = Math.log10(result.mag); - } //bugfix: before we normalize: if we started with 0, we now need to manually fix a layer ourselves! - - + } + //bugfix: before we normalize: if we started with 0, we now need to manually fix a layer ourselves! if (result.sign === 0) { result.sign = 1; - if (result.mag === 0 && result.layer >= 1) { result.layer -= 1; result.mag = 1; } } - - result.normalize(); //layeradd10: like adding 'diff' to the number's slog(base) representation. Very similar to tetrate base 10 and iterated log base 10. Also equivalent to adding a fractional amount to the number's layer in its break_eternity.js representation. - + result.normalize(); + //layeradd10: like adding 'diff' to the number's slog(base) representation. Very similar to tetrate base 10 and iterated log base 10. Also equivalent to adding a fractional amount to the number's layer in its break_eternity.js representation. if (diff !== 0) { - return result.layeradd(diff, 10); //safe, only calls positive height 1 payload tetration, slog and log + return result.layeradd(diff, 10, linear); //safe, only calls positive height 1 payload tetration, slog and log } return result; - } //layeradd: like adding 'diff' to the number's slog(base) representation. Very similar to tetrate base 'base' and iterated log base 'base'. - + } + //layeradd: like adding 'diff' to the number's slog(base) representation. Very similar to tetrate base 'base' and iterated log base 'base'. }, { 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 slogdest = slogthis + diff; - if (slogdest >= 0) { - return Decimal.tetrate(base, slogdest); + return Decimal.tetrate(base, slogdest, Decimal.dOne, linear); } else if (!Number.isFinite(slogdest)) { return Decimal.dNaN; } else if (slogdest >= -1) { - return Decimal.log(Decimal.tetrate(base, slogdest + 1), base); + return Decimal.log(Decimal.tetrate(base, slogdest + 1, Decimal.dOne, linear), base); } else { - return Decimal.log(Decimal.log(Decimal.tetrate(base, slogdest + 2), base), base); + return Decimal.log(Decimal.log(Decimal.tetrate(base, slogdest + 2, Decimal.dOne, linear), base), base); } - } //The Lambert W function, also called the omega function or product logarithm, is the solution W(x) === x*e^x. + } + //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 //Some special values, for testing: https://en.wikipedia.org/wiki/Lambert_W_function#Special_values - }, { key: "lambertw", value: function lambertw() { @@ -2322,78 +2134,346 @@ var Decimal = /*#__PURE__*/function () { } else if (this.layer === 2) { return d_lambertw(this); } - if (this.layer >= 3) { return FC_NN(this.sign, this.layer - 1, this.mag); } - throw "Unhandled behavior in lambertw()"; - } //The super square-root function - what number, tetrated to height 2, equals this? + } + //The super square-root function - what number, tetrated to height 2, equals this? //Other sroots are possible to calculate probably through guess and check methods, this one is easy though. // https://en.wikipedia.org/wiki/Tetration#Super-root - }, { key: "ssqrt", value: function ssqrt() { if (this.sign == 1 && this.layer >= 3) { return FC_NN(this.sign, this.layer - 1, this.mag); } - var lnx = this.ln(); return lnx.div(lnx.lambertw()); - } //Pentation/pentate: The result of tetrating 'height' times in a row. An absurdly strong operator - Decimal.pentate(2, 4.28) and Decimal.pentate(10, 2.37) are already too huge for break_eternity.js! - // https://en.wikipedia.org/wiki/Pentation + } + //Super-root, one of tetration's inverses - what number, tetrated to height (height), equals this? + //Only works with the linear approximation, because I don't know the structure of non-linear tetrations for inputs < 1 + //TODO: Optimize this like how slog is optimized + }, { + key: "linear_sroot", + value: function linear_sroot(degree) { + //1st-degree super root just returns its input + if (degree == 1) { + return this; + } + if (this.eq(Decimal.dInf)) { + return Decimal.dInf; + } + if (!this.isFinite()) { + return Decimal.dNaN; + } + //ssqrt handles square super-root faster + if (degree == 2) { + try { + //ssqrt uses lambertw which throws an error if the number is too small + return this.ssqrt(); + } catch (_a) { + return Decimal.dNaN; + } + } + //Using linear approximation, x^^n = x^n if 0 < n < 1 + if (degree > 0 && degree < 1) { + return this.root(degree); + } + //Using the linear approximation, there actually is a single solution for super roots with -2 < degree <= -1 + if (degree > -2 && degree < -1) { + return Decimal.fromNumber(degree).add(2).pow(this.recip()); + } + //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; + } + //Infinite degree super-root is x^(1/x) between 1/e <= x <= e, undefined otherwise + if (degree == Number.POSITIVE_INFINITY) { + var this_num = this.toNumber(); + if (this_num < Math.E && this_num > _EXPN1) { + return this.pow(this.recip()); + } else { + return Decimal.dNaN; + } + } + //Special case: any super-root of 1 is 1 + if (this.eq(1)) { + return Decimal.dOne; + } + //TODO: base < 0 (It'll probably be NaN anyway) + if (this.lt(0)) { + return Decimal.dNaN; + } + //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; + } + //this > 1 + if (this.gt(1)) { + //Uses guess-and-check to find the super-root. + //If this > 10^^(degree), then the answer is under iteratedlog(10, degree - 1): for example, ssqrt(x) < log(x, 10) as long as x > 10^10, and linear_sroot(x, 3) < log(log(x, 10), 10) as long as x > 10^10^10 + //On the other hand, if this < 10^^(degree), then clearly the answer is less than 10 + //Since the answer could be a higher-layered number itself (whereas slog's maximum is 1.8e308), the guess-and-check is scaled to the layer of the upper bound, so the guess is set to the average of some higher-layer exponents of the bounds rather than the bounds itself (as taking plain averages on tetrational-scale numbers would go nowhere) + var upperBound = Decimal.dTen; + if (this.gte(Decimal.tetrate(10, degree, 1, true))) { + upperBound = this.iteratedlog(10, degree - 1, true); + } + if (degree <= 1) { + upperBound = this.root(degree); + } + var lower = Decimal.dZero; //This is zero rather than one because we might be on a higher layer, so the lower bound might actually some 10^10^10...^0 + var layer = upperBound.layer; + var upper = upperBound.iteratedlog(10, layer, true); + var previous = upper; + var guess = upper.div(2); + var loopGoing = true; + while (loopGoing) { + guess = lower.add(upper).div(2); + if (Decimal.iteratedexp(10, layer, guess, true).tetrate(degree, 1, true).gt(this)) upper = guess;else lower = guess; + if (guess.eq(previous)) loopGoing = false;else previous = guess; + } + return Decimal.iteratedexp(10, layer, guess, true); + } + //0 < this < 1 + else { + //A tetration of decimal degree can potentially have three different portions, as shown at https://www.desmos.com/calculator/ayvqks6mxa, which is a graph of x^^2.05: + //The portion where the function is increasing, extending from a minimum (which may be at x = 0 or at some x between 0 and 1) up to infinity (I'll call this the "increasing" range) + //The portion where the function is decreasing (I'll call this the "decreasing" range) + //A small, steep increasing portion very close to x = 0 (I'll call this the "zero" range) + //If ceiling(degree) is even, then the tetration will either be strictly increasing, or it will have the increasing and decreasing ranges, but not the zero range (because if ceiling(degree) is even, 0^^degree == 1). + //If ceiling(degree) is odd, then the tetration will either be strictly increasing, or it will have all three ranges (because if ceiling(degree) is odd, 0^^degree == 0). + //The existence of these ranges means that a super-root could potentially have two or three valid answers. + //Out of these, we'd prefer the increasing range value if it exists, otherwise we'll take the zero range value (it can't have a decreasing range value if it doesn't have an increasing range value) if the zero range exists. + //It's possible to identify which range that "this" is in: + //If the tetration is decreasing at that point, the point is in the decreasing range. + //If the tetration is increasing at that point and ceiling(degree) is even, the point is in the increasing range since there is no zero range. + //If the tetration is increasing at that point and ceiling(degree) is odd, look at the second derivative at that point. If the second derivative is positive, the point is in the increasing range. If the second derivative is negative, the point is the zero range. + //We need to find the local minimum (separates decreasing and increasing ranges) and the local maximum (separates zero and decreasing ranges). + //(stage) is which stage of the loop we're in: stage 1 is finding the minimum, stage 2 means we're between the stages, and stage 3 is finding the maximum. + //The boundary between the decreasing range and the zero range can be very small, so we want to use layer -1 numbers. Therefore, all numbers involved are log10(recip()) of their actual values. + var stage = 1; + var minimum = FC(1, 10, 1); + var maximum = FC(1, 10, 1); + var _lower = FC(1, 10, 1); //eeeeeeeee-10, which is effectively 0; I would use Decimal.dInf but its reciprocal is NaN + var _upper = FC(1, 1, -16); //~ 1 - 1e-16 + var prevspan = Decimal.dZero; + var difference = FC(1, 10, 1); + var _upperBound = _upper.pow10().recip(); + var distance = Decimal.dZero; + var prevPoint = _upperBound; + var nextPoint = _upperBound; + var evenDegree = Math.ceil(degree) % 2 == 0; + var range = 0; + var lastValid = FC(1, 10, 1); + var infLoopDetector = false; + var previousUpper = Decimal.dZero; + var decreasingFound = false; + while (stage < 4) { + if (stage == 2) { + //The minimum has been found. If ceiling(degree) is even, there's no zero range and thus no local maximum, so end the loop here. Otherwise, begin finding the maximum. + if (evenDegree) break;else { + _lower = FC(1, 10, 1); + _upper = minimum; + stage = 3; + difference = FC(1, 10, 1); + lastValid = FC(1, 10, 1); + } + } + infLoopDetector = false; + while (_upper.neq(_lower)) { + previousUpper = _upper; + if (_upper.pow10().recip().tetrate(degree, 1, true).eq(1) && _upper.pow10().recip().lt(0.4)) { + _upperBound = _upper.pow10().recip(); + prevPoint = _upper.pow10().recip(); + nextPoint = _upper.pow10().recip(); + distance = Decimal.dZero; + range = -1; //This would cause problems with degree < 1 in the linear approximation... but those are already covered as a special case + if (stage == 3) lastValid = _upper; + } else if (_upper.pow10().recip().tetrate(degree, 1, true).eq(_upper.pow10().recip()) && !evenDegree && _upper.pow10().recip().lt(0.4)) { + _upperBound = _upper.pow10().recip(); + prevPoint = _upper.pow10().recip(); + nextPoint = _upper.pow10().recip(); + distance = Decimal.dZero; + range = 0; + } else if (_upper.pow10().recip().tetrate(degree, 1, true).eq(_upper.pow10().recip().mul(2).tetrate(degree, 1, true))) { + //If the upper bound is closer to zero than the next point with a discernable tetration, so surely it's in whichever range is closest to zero? + //This won't happen in a strictly increasing tetration, as there x^^degree ~= x as x approaches zero + _upperBound = _upper.pow10().recip(); + prevPoint = Decimal.dZero; + nextPoint = _upperBound.mul(2); + distance = _upperBound; + if (evenDegree) range = -1;else range = 0; + } else { + //We want to use prevspan to find the "previous point" right before the upper bound and the "next point" right after the upper bound, as that will let us approximate derivatives + prevspan = _upper.mul(1.2e-16); + _upperBound = _upper.pow10().recip(); + prevPoint = _upper.add(prevspan).pow10().recip(); + distance = _upperBound.sub(prevPoint); + nextPoint = _upperBound.add(distance); + //...but it's of no use to us while its tetration is equal to upper's tetration, so widen the difference until it's not + //We add prevspan and subtract nextspan because, since upper is log10(recip(upper bound)), the upper bound gets smaller as upper gets larger and vice versa + while (prevPoint.tetrate(degree, 1, true).eq(_upperBound.tetrate(degree, 1, true)) || nextPoint.tetrate(degree, 1, true).eq(_upperBound.tetrate(degree, 1, true)) || prevPoint.gte(_upperBound) || nextPoint.lte(_upperBound)) { + prevspan = prevspan.mul(2); + prevPoint = _upper.add(prevspan).pow10().recip(); + distance = _upperBound.sub(prevPoint); + nextPoint = _upperBound.add(distance); + } + if (stage == 1 && nextPoint.tetrate(degree, 1, true).gt(_upperBound.tetrate(degree, 1, true)) && prevPoint.tetrate(degree, 1, true).gt(_upperBound.tetrate(degree, 1, true)) || stage == 3 && nextPoint.tetrate(degree, 1, true).lt(_upperBound.tetrate(degree, 1, true)) && prevPoint.tetrate(degree, 1, true).lt(_upperBound.tetrate(degree, 1, true))) { + lastValid = _upper; + } + if (nextPoint.tetrate(degree, 1, true).lt(_upperBound.tetrate(degree, 1, true))) { + //Derivative is negative, so we're in decreasing range + range = -1; + } else if (evenDegree) { + //No zero range, so we're in increasing range + range = 1; + } else if (stage == 3 && _upper.gt_tolerance(minimum, 1e-8)) { + //We're already below the minimum, so we can't be in range 1 + range = 0; + } else { + //Number imprecision has left the second derivative somewhat untrustworthy, so we need to expand the bounds to ensure it's correct + while (prevPoint.tetrate(degree, 1, true).eq_tolerance(_upperBound.tetrate(degree, 1, true), 1e-8) || nextPoint.tetrate(degree, 1, true).eq_tolerance(_upperBound.tetrate(degree, 1, true), 1e-8) || prevPoint.gte(_upperBound) || nextPoint.lte(_upperBound)) { + prevspan = prevspan.mul(2); + prevPoint = _upper.add(prevspan).pow10().recip(); + distance = _upperBound.sub(prevPoint); + nextPoint = _upperBound.add(distance); + } + if (nextPoint.tetrate(degree, 1, true).sub(_upperBound.tetrate(degree, 1, true)).lt(_upperBound.tetrate(degree, 1, true).sub(prevPoint.tetrate(degree, 1, true)))) { + //Second derivative is negative, so we're in zero range + range = 0; + } else { + //By process of elimination, we're in increasing range + range = 1; + } + } + } + if (range == -1) decreasingFound = true; + if (stage == 1 && range == 1 || stage == 3 && range != 0) { + //The upper bound is too high + if (_lower.eq(FC(1, 10, 1))) { + _upper = _upper.mul(2); + } else { + var cutOff = false; + if (infLoopDetector && (range == 1 && stage == 1 || range == -1 && stage == 3)) cutOff = true; //Avoids infinite loops from floating point imprecision + _upper = _upper.add(_lower).div(2); + if (cutOff) break; + } + } else { + if (_lower.eq(FC(1, 10, 1))) { + //We've now found an actual lower bound + _lower = _upper; + _upper = _upper.div(2); + } else { + //The upper bound is too low, meaning last time we decreased the upper bound, we should have gone to the other half of the new range instead + var _cutOff = false; + if (infLoopDetector && (range == 1 && stage == 1 || range == -1 && stage == 3)) _cutOff = true; //Avoids infinite loops from floating point imprecision + _lower = _lower.sub(difference); + _upper = _upper.sub(difference); + if (_cutOff) break; + } + } + if (_lower.sub(_upper).div(2).abs().gt(difference.mul(1.5))) infLoopDetector = true; + difference = _lower.sub(_upper).div(2).abs(); + if (_upper.gt("1e18")) break; + if (_upper.eq(previousUpper)) break; //Another infinite loop catcher + } + if (_upper.gt("1e18")) break; + if (!decreasingFound) break; //If there's no decreasing range, then even if an error caused lastValid to gain a value, the minimum can't exist + if (lastValid == FC(1, 10, 1)) { + //Whatever we're searching for, it doesn't exist. If there's no minimum, then there's no maximum either, so either way we can end the loop here. + break; + } + if (stage == 1) minimum = lastValid;else if (stage == 3) maximum = lastValid; + stage++; + } + //Now we have the minimum and maximum, so it's time to calculate the actual super-root. + //First, check if the root is in the increasing range. + _lower = minimum; + _upper = FC(1, 1, -18); + var _previous = _upper; + var _guess = Decimal.dZero; + var _loopGoing = true; + while (_loopGoing) { + 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; + } + //using guess.neq(minimum) led to imprecision errors, so here's a fixed version of that + if (!_guess.eq_tolerance(minimum, 1e-15)) { + return _guess.pow10().recip(); + } else { + //If guess == minimum, we haven't actually found the super-root, the algorithm just kept going down trying to find a super-root that's not in the increasing range. + //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; + } + _lower = FC(1, 10, 1); + _upper = maximum; + _previous = _upper; + _guess = Decimal.dZero; + _loopGoing = true; + while (_loopGoing) { + 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; + } + return _guess.pow10().recip(); + } + } + } + //Pentation/pentate: The result of tetrating 'height' times in a row. An absurdly strong operator - Decimal.pentate(2, 4.28) and Decimal.pentate(10, 2.37) are already too huge for break_eternity.js! + // https://en.wikipedia.org/wiki/Pentation }, { key: "pentate", value: function pentate() { 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); var oldheight = height; height = Math.trunc(height); - var fracheight = oldheight - height; //I have no idea if this is a meaningful approximation for pentation to continuous heights, but it is monotonic and continuous. - + var fracheight = oldheight - height; + //I have no idea if this is a meaningful approximation for pentation to continuous heights, but it is monotonic and continuous. if (fracheight !== 0) { if (payload.eq(Decimal.dOne)) { ++height; payload = Decimal.fromNumber(fracheight); } else { if (this.eq(10)) { - payload = payload.layeradd10(fracheight); + payload = payload.layeradd10(fracheight, linear); } else { - payload = payload.layeradd(fracheight, this); + payload = payload.layeradd(fracheight, this, linear); } } } - for (var i = 0; i < height; ++i) { - payload = this.tetrate(payload.toNumber()); //bail if we're NaN - + payload = this.tetrate(payload.toNumber(), Decimal.dOne, linear); + //bail if we're NaN if (!isFinite(payload.layer) || !isFinite(payload.mag)) { return payload.normalize(); - } //give up after 10 iterations if nothing is happening - - + } + //give up after 10 iterations if nothing is happening if (i > 10) { return payload; } } - return payload; - } // trig functions! - + } + // trig functions! }, { key: "sin", value: function sin() { if (this.mag < 0) { return this; } - if (this.layer === 0) { return Decimal.fromNumber(Math.sin(this.sign * this.mag)); } - return FC_NN(0, 0, 0); } }, { @@ -2402,11 +2482,9 @@ var Decimal = /*#__PURE__*/function () { if (this.mag < 0) { return Decimal.dOne; } - if (this.layer === 0) { return Decimal.fromNumber(Math.cos(this.sign * this.mag)); } - return FC_NN(0, 0, 0); } }, { @@ -2415,11 +2493,9 @@ var Decimal = /*#__PURE__*/function () { if (this.mag < 0) { return this; } - if (this.layer === 0) { return Decimal.fromNumber(Math.tan(this.sign * this.mag)); } - return FC_NN(0, 0, 0); } }, { @@ -2428,11 +2504,9 @@ var Decimal = /*#__PURE__*/function () { if (this.mag < 0) { return this; } - if (this.layer === 0) { return Decimal.fromNumber(Math.asin(this.sign * this.mag)); } - return FC_NN(Number.NaN, Number.NaN, Number.NaN); } }, { @@ -2441,11 +2515,9 @@ var Decimal = /*#__PURE__*/function () { if (this.mag < 0) { return Decimal.fromNumber(Math.acos(this.toNumber())); } - if (this.layer === 0) { return Decimal.fromNumber(Math.acos(this.sign * this.mag)); } - return FC_NN(Number.NaN, Number.NaN, Number.NaN); } }, { @@ -2454,11 +2526,9 @@ var Decimal = /*#__PURE__*/function () { if (this.mag < 0) { return this; } - if (this.layer === 0) { return Decimal.fromNumber(Math.atan(this.sign * this.mag)); } - return Decimal.fromNumber(Math.atan(this.sign * 1.8e308)); } }, { @@ -2492,26 +2562,22 @@ var Decimal = /*#__PURE__*/function () { if (this.abs().gte(1)) { return FC_NN(Number.NaN, Number.NaN, Number.NaN); } - return Decimal.ln(this.add(1).div(Decimal.fromNumber(1).sub(this))).div(2); } /** * Joke function from Realm Grinder */ - }, { key: "ascensionPenalty", value: function ascensionPenalty(ascensions) { if (ascensions === 0) { return this; } - return this.root(Decimal.pow(10, ascensions)); } /** * Joke function from Cookie Clicker. It's 'egg' */ - }, { key: "egg", value: function egg() { @@ -2586,7 +2652,6 @@ var Decimal = /*#__PURE__*/function () { * Use `new Decimal(value)` to explicitly create a writeable copy if mutation * is required. */ - }, { key: "fromValue_noAlloc", value: function fromValue_noAlloc(value) { @@ -2594,11 +2659,9 @@ var Decimal = /*#__PURE__*/function () { return value; } else if (typeof value === "string") { var cached = Decimal.fromStringCache.get(value); - if (cached !== undefined) { return cached; } - return Decimal.fromString(value); } else if (typeof value === "number") { return Decimal.fromNumber(value); @@ -2724,6 +2787,21 @@ var Decimal = /*#__PURE__*/function () { value: function reciprocate(value) { return D(value).reciprocate(); } + }, { + key: "mod", + value: function mod(value, other) { + return D(value).mod(other); + } + }, { + key: "modulo", + value: function modulo(value, other) { + return D(value).modulo(other); + } + }, { + key: "modular", + value: function modular(value, other) { + return D(value).modular(other); + } }, { key: "cmp", value: function cmp(value, other) { @@ -2745,11 +2823,9 @@ var Decimal = /*#__PURE__*/function () { function isNaN(_x) { return _isNaN.apply(this, arguments); } - isNaN.toString = function () { return _isNaN.toString(); }; - return isNaN; }(function (value) { value = D(value); @@ -2761,11 +2837,9 @@ var Decimal = /*#__PURE__*/function () { function isFinite(_x2) { return _isFinite.apply(this, arguments); } - isFinite.toString = function () { return _isFinite.toString(); }; - return isFinite; }(function (value) { value = D(value); @@ -2991,38 +3065,44 @@ var Decimal = /*#__PURE__*/function () { value: function tetrate(value) { var height = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2; var payload = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : FC_NN(1, 0, 1); - return D(value).tetrate(height, payload); + var linear = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; + return D(value).tetrate(height, payload, linear); } }, { key: "iteratedexp", value: function iteratedexp(value) { var height = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2; var payload = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : FC_NN(1, 0, 1); - return D(value).iteratedexp(height, payload); + var linear = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; + return D(value).iteratedexp(height, payload, linear); } }, { key: "iteratedlog", value: function iteratedlog(value) { var base = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 10; var times = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1; - return D(value).iteratedlog(base, times); + var linear = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; + return D(value).iteratedlog(base, times, linear); } }, { key: "layeradd10", value: function layeradd10(value, diff) { - return D(value).layeradd10(diff); + var linear = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + return D(value).layeradd10(diff, linear); } }, { key: "layeradd", value: function layeradd(value, diff) { var base = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 10; - return D(value).layeradd(diff, base); + var linear = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; + return D(value).layeradd(diff, base, linear); } }, { key: "slog", value: function slog(value) { var base = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 10; - return D(value).slog(base); + var linear = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + return D(value).slog(base, 100, linear); } }, { key: "lambertw", @@ -3034,12 +3114,18 @@ var Decimal = /*#__PURE__*/function () { value: function ssqrt(value) { return D(value).ssqrt(); } + }, { + key: "linear_sroot", + value: function linear_sroot(value, height) { + return D(value).linear_sroot(height); + } }, { key: "pentate", value: function pentate(value) { var height = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2; var payload = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : FC_NN(1, 0, 1); - return D(value).pentate(height, payload); + var linear = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; + return D(value).pentate(height, payload, linear); } /** * If you're willing to spend 'resourcesAvailable' and want to buy something @@ -3047,7 +3133,6 @@ var Decimal = /*#__PURE__*/function () { * multiply by priceRatio, already own currentOwned), how much of it can you buy? * Adapted from Trimps source code. */ - }, { key: "affordGeometricSeries", value: function affordGeometricSeries(resourcesAvailable, priceStart, priceRatio, currentOwned) { @@ -3057,7 +3142,6 @@ var Decimal = /*#__PURE__*/function () { * How much resource would it cost to buy (numItems) items if you already have currentOwned, * the initial price is priceStart and it multiplies by priceRatio each purchase? */ - }, { key: "sumGeometricSeries", value: function sumGeometricSeries(numItems, priceStart, priceRatio, currentOwned) { @@ -3068,7 +3152,6 @@ var Decimal = /*#__PURE__*/function () { * increasing cost each purchase (start at priceStart, add by priceAdd, already own currentOwned), * how much of it can you buy? */ - }, { key: "affordArithmeticSeries", value: function affordArithmeticSeries(resourcesAvailable, priceStart, priceAdd, currentOwned) { @@ -3079,7 +3162,6 @@ var Decimal = /*#__PURE__*/function () { * the initial price is priceStart and it adds priceAdd each purchase? * Adapted from http://www.mathwords.com/a/arithmetic_series.htm */ - }, { key: "sumArithmeticSeries", value: function sumArithmeticSeries(numItems, priceStart, priceAdd, currentOwned) { @@ -3091,7 +3173,6 @@ var Decimal = /*#__PURE__*/function () { * From Frozen Cookies: * http://cookieclicker.wikia.com/wiki/Frozen_Cookies_(JavaScript_Add-on)#Efficiency.3F_What.27s_that.3F */ - }, { key: "efficiencyOfPurchase", value: function efficiencyOfPurchase(cost, currentRpS, deltaRpS) { @@ -3105,27 +3186,23 @@ var Decimal = /*#__PURE__*/function () { if (Math.random() * 20 < 1) { return FC_NN(0, 0, 0); } - - var randomsign = Math.random() > 0.5 ? 1 : -1; //5% of the time, return 1 or -1 - + var randomsign = Math.random() > 0.5 ? 1 : -1; + //5% of the time, return 1 or -1 if (Math.random() * 20 < 1) { return FC_NN(randomsign, 0, 1); - } //pick a random layer - - + } + //pick a random layer var layer = Math.floor(Math.random() * (maxLayers + 1)); - var randomexp = layer === 0 ? Math.random() * 616 - 308 : Math.random() * 16; //10% of the time, make it a simple power of 10 - + var randomexp = layer === 0 ? Math.random() * 616 - 308 : Math.random() * 16; + //10% of the time, make it a simple power of 10 if (Math.random() > 0.9) { randomexp = Math.trunc(randomexp); } - - var randommag = Math.pow(10, randomexp); //10% of the time, trunc mag - + var randommag = Math.pow(10, randomexp); + //10% of the time, trunc mag if (Math.random() > 0.9) { randommag = Math.trunc(randommag); } - return FC(randomsign, layer, randommag); } }, { @@ -3154,7 +3231,6 @@ var Decimal = /*#__PURE__*/function () { key: "sumArithmeticSeries_core", value: function sumArithmeticSeries_core(numItems, priceStart, priceAdd, currentOwned) { var actualStart = priceStart.add(currentOwned.mul(priceAdd)); // (n/2)*(2*a+(n-1)*d) - return numItems.div(2).mul(actualStart.mul(2).plus(numItems.sub(1).mul(priceAdd))); } }, { @@ -3169,7 +3245,6 @@ var Decimal = /*#__PURE__*/function () { if (base > 10) { return height - 1; } - return Decimal.critical_section(base, height, critical_slog_values); } }, { @@ -3182,30 +3257,25 @@ var Decimal = /*#__PURE__*/function () { value: function critical_section(base, height, grid) { //this part is simple at least, since it's just 0.1 to 0.9 height *= 10; - if (height < 0) { height = 0; } - if (height > 10) { height = 10; - } //have to do this complicated song and dance since one of the critical_headers is Math.E, and in the future I'd like 1.5 as well - - + } + //have to do this complicated song and dance since one of the critical_headers is Math.E, and in the future I'd like 1.5 as well if (base < 2) { base = 2; } - if (base > 10) { base = 10; } - var lower = 0; - var upper = 0; //basically, if we're between bases, we interpolate each bases' relevant values together + var upper = 0; + //basically, if we're between bases, we interpolate each bases' relevant values together //then we interpolate based on what the fractional height is. //accuracy could be improved by doing a non-linear interpolation (maybe), by adding more bases and heights (definitely) but this is AFAIK the best you can get without running some pari.gp or mathematica program to calculate exact values //however, do note http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html can do it for arbitrary heights but not for arbitrary bases (2, e, 10 present) - for (var i = 0; i < critical_headers.length; ++i) { if (critical_headers[i] == base) { // exact match @@ -3220,11 +3290,10 @@ var Decimal = /*#__PURE__*/function () { break; } } - - var frac = height - Math.floor(height); //improvement - you get more accuracy (especially around 0.9-1.0) by doing log, then frac, then powing the result + var frac = height - Math.floor(height); + //improvement - you get more accuracy (especially around 0.9-1.0) by doing log, then frac, then powing the result //(we could pre-log the lookup table, but then fractional bases would get Weird) //also, use old linear for slog (values 0 or less in critical section). maybe something else is better but haven't thought about what yet - if (lower <= 0 || upper <= 0) { return lower * (1 - frac) + upper * frac; } else { @@ -3232,7 +3301,6 @@ var Decimal = /*#__PURE__*/function () { } } }]); - return Decimal; }(); Decimal.dZero = FC_NN(0, 0, 0); @@ -3245,16 +3313,16 @@ Decimal.dInf = FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); Decimal.dNegInf = FC_NN(-1, Number.NEGATIVE_INFINITY, Number.NEGATIVE_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); // return Decimal; +Decimal.fromStringCache = new LRUCache(DEFAULT_FROM_STRING_CACHE_SIZE); +// return Decimal; // Optimise Decimal aliases. // We can't do this optimisation before Decimal is assigned. - D = Decimal.fromValue_noAlloc; FC = Decimal.fromComponents; -FC_NN = Decimal.fromComponents_noNormalize; // eslint-disable-next-line @typescript-eslint/no-unused-vars - -Decimal.fromMantissaExponent; // eslint-disable-next-line @typescript-eslint/no-unused-vars - +FC_NN = Decimal.fromComponents_noNormalize; +// eslint-disable-next-line @typescript-eslint/no-unused-vars +Decimal.fromMantissaExponent; +// eslint-disable-next-line @typescript-eslint/no-unused-vars Decimal.fromMantissaExponent_noNormalize; module.exports = Decimal; diff --git a/break_eternity.esm.js b/break_eternity.esm.js index 22bb1b5..13c3344 100644 --- a/break_eternity.esm.js +++ b/break_eternity.esm.js @@ -3,17 +3,15 @@ function _classCallCheck(instance, Constructor) { throw new TypeError("Cannot call a class as a function"); } } - function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, descriptor.key, descriptor); + Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } - function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); @@ -22,6 +20,20 @@ function _createClass(Constructor, protoProps, staticProps) { }); return Constructor; } +function _toPrimitive(input, hint) { + if (typeof input !== "object" || input === null) return input; + var prim = input[Symbol.toPrimitive]; + if (prim !== undefined) { + var res = prim.call(input, hint || "default"); + if (typeof res !== "object") return res; + throw new TypeError("@@toPrimitive must return a primitive value."); + } + return (hint === "string" ? String : Number)(input); +} +function _toPropertyKey(arg) { + var key = _toPrimitive(arg, "string"); + return typeof key === "symbol" ? key : String(key); +} /** * A LRU cache intended for caching pure functions. @@ -37,18 +49,16 @@ var LRUCache = /*#__PURE__*/function () { */ function LRUCache(maxSize) { _classCallCheck(this, LRUCache); - - this.map = new Map(); // Invariant: Exactly one of the below is true before and after calling a + this.map = new Map(); + // Invariant: Exactly one of the below is true before and after calling a // LRUCache method: // - first and last are both undefined, and map.size() is 0. // - first and last are the same object, and map.size() is 1. // - first and last are different objects, and map.size() is greater than 1. - this.first = undefined; this.last = undefined; this.maxSize = maxSize; } - _createClass(LRUCache, [{ key: "size", get: function get() { @@ -60,53 +70,48 @@ var LRUCache = /*#__PURE__*/function () { * @param key The key to get. * @returns The cached value, or undefined if key is not in the cache. */ - }, { key: "get", value: function get(key) { var node = this.map.get(key); - if (node === undefined) { return undefined; - } // It is guaranteed that there is at least one item in the cache. + } + // It is guaranteed that there is at least one item in the cache. // Therefore, first and last are guaranteed to be a ListNode... // but if there is only one item, they might be the same. // Update the order of the list to make this node the first node in the // list. // This isn't needed if this node is already the first node in the list. - - if (node !== this.first) { // As this node is DIFFERENT from the first node, it is guaranteed that // there are at least two items in the cache. // However, this node could possibly be the last item. if (node === this.last) { // This node IS the last node. - this.last = node.prev; // From the invariants, there must be at least two items in the cache, + this.last = node.prev; + // From the invariants, there must be at least two items in the cache, // so node - which is the original "last node" - must have a defined // previous node. Therefore, this.last - set above - must be defined // here. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.last.next = undefined; } else { // This node is somewhere in the middle of the list, so there must be at // least THREE items in the list, and this node's prev and next must be // defined here. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - node.prev.next = node.next; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - + node.prev.next = node.next; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion node.next.prev = node.prev; } - - node.next = this.first; // From the invariants, there must be at least two items in the cache, so + node.next = this.first; + // From the invariants, there must be at least two items in the cache, so // this.first must be a valid ListNode. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.first.prev = node; this.first = node; } - return node.value; } /** @@ -116,7 +121,6 @@ var LRUCache = /*#__PURE__*/function () { * @param value The value of the entry. * @throws Error, if the map already contains the key. */ - }, { key: "set", value: function set(key, value) { @@ -124,13 +128,11 @@ var LRUCache = /*#__PURE__*/function () { if (this.maxSize < 1) { return; } - if (this.map.has(key)) { throw new Error("Cannot update existing keys in the cache"); } - - var node = new ListNode(key, value); // Move node to the front of the list. - + var node = new ListNode(key, value); + // Move node to the front of the list. if (this.first === undefined) { // If the first is undefined, the last is undefined too. // Therefore, this cache has no items in it. @@ -142,9 +144,7 @@ var LRUCache = /*#__PURE__*/function () { this.first.prev = node; this.first = node; } - this.map.set(key, node); - while (this.map.size > this.maxSize) { // We are guaranteed that this.maxSize >= 1, // so this.map.size is guaranteed to be >= 2, @@ -153,22 +153,19 @@ var LRUCache = /*#__PURE__*/function () { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion var last = this.last; this.map["delete"](last.key); - this.last = last.prev; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - + this.last = last.prev; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion this.last.next = undefined; } } }]); - return LRUCache; }(); /** * A node in a doubly linked list. */ - var ListNode = /*#__PURE__*/_createClass(function ListNode(key, value) { _classCallCheck(this, ListNode); - this.next = undefined; this.prev = undefined; this.key = key; @@ -176,112 +173,110 @@ var ListNode = /*#__PURE__*/_createClass(function ListNode(key, value) { }); var MAX_SIGNIFICANT_DIGITS = 17; //Maximum number of digits of precision to assume in Number - var EXP_LIMIT = 9e15; //If we're ABOVE this value, increase a layer. (9e15 is close to the largest integer that can fit in a Number.) - var LAYER_DOWN = Math.log10(9e15); var FIRST_NEG_LAYER = 1 / 9e15; //At layer 0, smaller non-zero numbers than this become layer 1 numbers with negative mag. After that the pattern continues as normal. - var NUMBER_EXP_MAX = 308; //The largest exponent that can appear in a Number, though not all mantissas are valid here. - var NUMBER_EXP_MIN = -324; //The smallest exponent that can appear in a Number, though not all mantissas are valid here. - var MAX_ES_IN_A_ROW = 5; //For default toString behaviour, when to swap from eee... to (e^n) syntax. - var DEFAULT_FROM_STRING_CACHE_SIZE = (1 << 10) - 1; // The default size of the LRU cache used to cache Decimal.fromString. - var powerOf10 = function () { // We need this lookup table because Math.pow(10, exponent) // when exponent's absolute value is large is slightly inaccurate. // You can fix it with the power of math... or just make a lookup table. // Faster AND simpler var powersOf10 = []; - for (var i = NUMBER_EXP_MIN + 1; i <= NUMBER_EXP_MAX; i++) { powersOf10.push(Number("1e" + i)); } - var indexOf0InPowersOf10 = 323; return function (power) { return powersOf10[power + indexOf0InPowersOf10]; }; -}(); //tetration/slog to real height stuff +}(); +//tetration/slog to real height stuff //background info and tables of values for critical functions taken here: https://github.com/Patashu/break_eternity.js/issues/22 - - var critical_headers = [2, Math.E, 3, 4, 5, 6, 7, 8, 9, 10]; -var critical_tetr_values = [[// Base 2 (using http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html ) -1, 1.0891180521811202527, 1.1789767925673958433, 1.2701455431742086633, 1.3632090180450091941, 1.4587818160364217007, 1.5575237916251418333, 1.6601571006859253673, 1.7674858188369780435, 1.8804192098842727359, 2], [// Base E (using http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html ) +var critical_tetr_values = [[ +// Base 2 (using http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html ) +1, 1.0891180521811202527, 1.1789767925673958433, 1.2701455431742086633, 1.3632090180450091941, 1.4587818160364217007, 1.5575237916251418333, 1.6601571006859253673, 1.7674858188369780435, 1.8804192098842727359, 2], [ +// Base E (using http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html ) 1, 1.1121114330934078681, 1.2310389249316089299, 1.3583836963111376089, 1.4960519303993531879, 1.6463542337511945810, 1.8121385357018724464, 1.9969713246183068478, 2.2053895545527544330, 2.4432574483385252544, Math.E //1.0 -], [// Base 3 -1, 1.1187738849693603, 1.2464963939368214, 1.38527004705667, 1.5376664685821402, 1.7068895236551784, 1.897001227148399, 2.1132403089001035, 2.362480153784171, 2.6539010333870774, 3], [// Base 4 -1, 1.1367350847096405, 1.2889510672956703, 1.4606478703324786, 1.6570295196661111, 1.8850062585672889, 2.1539465047453485, 2.476829779693097, 2.872061932789197, 3.3664204535587183, 4], [// Base 5 -1, 1.1494592900767588, 1.319708228183931, 1.5166291280087583, 1.748171114438024, 2.0253263297298045, 2.3636668498288547, 2.7858359149579424, 3.3257226212448145, 4.035730287722532, 5], [// Base 6 -1, 1.159225940787673, 1.343712473580932, 1.5611293155111927, 1.8221199554561318, 2.14183924486326, 2.542468319282638, 3.0574682501653316, 3.7390572020926873, 4.6719550537360774, 6], [// Base 7 -1, 1.1670905356972596, 1.3632807444991446, 1.5979222279405536, 1.8842640123816674, 2.2416069644878687, 2.69893426559423, 3.3012632110403577, 4.121250340630164, 5.281493033448316, 7], [// Base 8 -1, 1.1736630594087796, 1.379783782386201, 1.6292821855668218, 1.9378971836180754, 2.3289975651071977, 2.8384347394720835, 3.5232708454565906, 4.478242031114584, 5.868592169644505, 8], [// Base 9 -1, 1.1793017514670474, 1.394054150657457, 1.65664127441059, 1.985170999970283, 2.4069682290577457, 2.9647310119960752, 3.7278665320924946, 4.814462547283592, 6.436522247411611, 9], [// Base 10 (using http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html ) +], [ +// Base 3 +1, 1.1187738849693603, 1.2464963939368214, 1.38527004705667, 1.5376664685821402, 1.7068895236551784, 1.897001227148399, 2.1132403089001035, 2.362480153784171, 2.6539010333870774, 3], [ +// Base 4 +1, 1.1367350847096405, 1.2889510672956703, 1.4606478703324786, 1.6570295196661111, 1.8850062585672889, 2.1539465047453485, 2.476829779693097, 2.872061932789197, 3.3664204535587183, 4], [ +// Base 5 +1, 1.1494592900767588, 1.319708228183931, 1.5166291280087583, 1.748171114438024, 2.0253263297298045, 2.3636668498288547, 2.7858359149579424, 3.3257226212448145, 4.035730287722532, 5], [ +// Base 6 +1, 1.159225940787673, 1.343712473580932, 1.5611293155111927, 1.8221199554561318, 2.14183924486326, 2.542468319282638, 3.0574682501653316, 3.7390572020926873, 4.6719550537360774, 6], [ +// Base 7 +1, 1.1670905356972596, 1.3632807444991446, 1.5979222279405536, 1.8842640123816674, 2.2416069644878687, 2.69893426559423, 3.3012632110403577, 4.121250340630164, 5.281493033448316, 7], [ +// Base 8 +1, 1.1736630594087796, 1.379783782386201, 1.6292821855668218, 1.9378971836180754, 2.3289975651071977, 2.8384347394720835, 3.5232708454565906, 4.478242031114584, 5.868592169644505, 8], [ +// Base 9 +1, 1.1793017514670474, 1.394054150657457, 1.65664127441059, 1.985170999970283, 2.4069682290577457, 2.9647310119960752, 3.7278665320924946, 4.814462547283592, 6.436522247411611, 9], [ +// Base 10 (using http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html ) 1, 1.1840100246247336579, 1.4061375836156954169, 1.6802272208863963918, 2.026757028388618927, 2.4770056063449647580, 3.0805252717554819987, 3.9191964192627283911, 5.1351528408331864230, 6.9899611795347148455, 10]]; -var critical_slog_values = [[// Base 2 --1, -0.9194161097107025, -0.8335625019330468, -0.7425599821143978, -0.6466611521029437, -0.5462617907227869, -0.4419033816638769, -0.3342645487554494, -0.224140440909962, -0.11241087890006762, 0], [// Base E +var critical_slog_values = [[ +// Base 2 +-1, -0.9194161097107025, -0.8335625019330468, -0.7425599821143978, -0.6466611521029437, -0.5462617907227869, -0.4419033816638769, -0.3342645487554494, -0.224140440909962, -0.11241087890006762, 0], [ +// Base E -1, -0.90603157029014, -0.80786507256596, -0.7064666939634, -0.60294836853664, -0.49849837513117, -0.39430303318768, -0.29147201034755, -0.19097820800866, -0.09361896280296, 0 //1.0 -], [// Base 3 --1, -0.9021579584316141, -0.8005762598234203, -0.6964780623319391, -0.5911906810998454, -0.486050182576545, -0.3823089430815083, -0.28106046722897615, -0.1831906535795894, -0.08935809204418144, 0], [// Base 4 --1, -0.8917227442365535, -0.781258746326964, -0.6705130326902455, -0.5612813129406509, -0.4551067709033134, -0.35319256652135966, -0.2563741554088552, -0.1651412821106526, -0.0796919581982668, 0], [// Base 5 --1, -0.8843387974366064, -0.7678744063886243, -0.6529563724510552, -0.5415870994657841, -0.4352842206588936, -0.33504449124791424, -0.24138853420685147, -0.15445285440944467, -0.07409659641336663, 0], [// Base 6 --1, -0.8786709358426346, -0.7577735191184886, -0.6399546189952064, -0.527284921869926, -0.4211627631006314, -0.3223479611761232, -0.23107655627789858, -0.1472057700818259, -0.07035171210706326, 0], [// Base 7 --1, -0.8740862815291583, -0.7497032990976209, -0.6297119746181752, -0.5161838335958787, -0.41036238255751956, -0.31277212146489963, -0.2233976621705518, -0.1418697367979619, -0.06762117662323441, 0], [// Base 8 --1, -0.8702632331800649, -0.7430366914122081, -0.6213373075161548, -0.5072025698095242, -0.40171437727184167, -0.30517930701410456, -0.21736343968190863, -0.137710238299109, -0.06550774483471955, 0], [// Base 9 --1, -0.8670016295947213, -0.7373984232432306, -0.6143173985094293, -0.49973884395492807, -0.394584953527678, -0.2989649949848695, -0.21245647317021688, -0.13434688362382652, -0.0638072667348083, 0], [// Base 10 +], [ +// Base 3 +-1, -0.9021579584316141, -0.8005762598234203, -0.6964780623319391, -0.5911906810998454, -0.486050182576545, -0.3823089430815083, -0.28106046722897615, -0.1831906535795894, -0.08935809204418144, 0], [ +// Base 4 +-1, -0.8917227442365535, -0.781258746326964, -0.6705130326902455, -0.5612813129406509, -0.4551067709033134, -0.35319256652135966, -0.2563741554088552, -0.1651412821106526, -0.0796919581982668, 0], [ +// Base 5 +-1, -0.8843387974366064, -0.7678744063886243, -0.6529563724510552, -0.5415870994657841, -0.4352842206588936, -0.33504449124791424, -0.24138853420685147, -0.15445285440944467, -0.07409659641336663, 0], [ +// Base 6 +-1, -0.8786709358426346, -0.7577735191184886, -0.6399546189952064, -0.527284921869926, -0.4211627631006314, -0.3223479611761232, -0.23107655627789858, -0.1472057700818259, -0.07035171210706326, 0], [ +// Base 7 +-1, -0.8740862815291583, -0.7497032990976209, -0.6297119746181752, -0.5161838335958787, -0.41036238255751956, -0.31277212146489963, -0.2233976621705518, -0.1418697367979619, -0.06762117662323441, 0], [ +// Base 8 +-1, -0.8702632331800649, -0.7430366914122081, -0.6213373075161548, -0.5072025698095242, -0.40171437727184167, -0.30517930701410456, -0.21736343968190863, -0.137710238299109, -0.06550774483471955, 0], [ +// Base 9 +-1, -0.8670016295947213, -0.7373984232432306, -0.6143173985094293, -0.49973884395492807, -0.394584953527678, -0.2989649949848695, -0.21245647317021688, -0.13434688362382652, -0.0638072667348083, 0], [ +// Base 10 -1, -0.8641642839543857, -0.732534623168535, -0.6083127477059322, -0.4934049257184696, -0.3885773075899922, -0.29376029055315767, -0.2083678561173622, -0.13155653399373268, -0.062401588652553186, 0]]; - var D = function D(value) { return Decimal.fromValue_noAlloc(value); }; - var FC = function FC(sign, layer, mag) { return Decimal.fromComponents(sign, layer, mag); }; - var FC_NN = function FC_NN(sign, layer, mag) { return Decimal.fromComponents_noNormalize(sign, layer, mag); -}; // eslint-disable-next-line @typescript-eslint/no-unused-vars - +}; var decimalPlaces = function decimalPlaces(value, places) { var len = places + 1; var numDigits = Math.ceil(Math.log10(Math.abs(value))); var rounded = Math.round(value * Math.pow(10, len - numDigits)) * Math.pow(10, numDigits - len); return parseFloat(rounded.toFixed(Math.max(len - numDigits, 0))); }; - var f_maglog10 = function f_maglog10(n) { return Math.sign(n) * Math.log10(Math.abs(n)); -}; //from HyperCalc source code - - +}; +//from HyperCalc source code var f_gamma = function f_gamma(n) { if (!isFinite(n)) { return n; } - if (n < -50) { if (n === Math.trunc(n)) { return Number.NEGATIVE_INFINITY; } - return 0; } - var scal1 = 1; - while (n < 10) { scal1 = scal1 * n; ++n; } - n -= 1; var l = 0.9189385332046727; //0.5*Math.log(2*Math.PI) - l = l + (n + 0.5) * Math.log(n); l = l - n; var n2 = n * n; @@ -303,99 +298,82 @@ var f_gamma = function f_gamma(n) { 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 - var f_lambertw = function f_lambertw(z) { var tol = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1e-10; 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; } 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); - if (Math.abs(wn - w) < tol * Math.abs(wn)) { return wn; } else { w = wn; } } - - throw Error("Iteration failed to converge: ".concat(z.toString())); //return Number.NaN; -}; //from https://github.com/scipy/scipy/blob/8dba340293fe20e62e173bdf2c10ae208286692f/scipy/special/lambertw.pxd + throw Error("Iteration failed to converge: ".concat(z.toString())); + //return Number.NaN; +}; +//from https://github.com/scipy/scipy/blob/8dba340293fe20e62e173bdf2c10ae208286692f/scipy/special/lambertw.pxd // 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) { var tol = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1e-10; var w; var ew, wewz, wn; - if (!Number.isFinite(z.mag)) { return z; } - if (z.eq(Decimal.dZero)) { return z; } - 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); //Halley's method; see 5.9 in [1] - + } + //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(); wewz = w.sub(z.mul(ew)); wn = w.sub(wewz.div(w.add(1).sub(w.add(2).mul(wewz).div(Decimal.mul(2, w).add(2))))); - if (Decimal.abs(wn.sub(w)).lt(Decimal.abs(wn).mul(tol))) { return wn; } else { w = wn; } } - - throw Error("Iteration failed to converge: ".concat(z.toString())); //return Decimal.dNaN; + throw Error("Iteration failed to converge: ".concat(z.toString())); + //return Decimal.dNaN; } /** - * The Decimal's value is simply mantissa * 10^exponent. + * The value of the Decimal is sign * 10^10^10...^mag, with (layer) 10s. If the layer is not 0, then negative mag means it's the reciprocal of the corresponding number with positive mag. */ - - var Decimal = /*#__PURE__*/function () { function Decimal(value) { _classCallCheck(this, Decimal); - this.sign = 0; this.mag = 0; this.layer = 0; - if (value instanceof Decimal) { this.fromDecimal(value); } else if (typeof value === "number") { @@ -404,23 +382,20 @@ var Decimal = /*#__PURE__*/function () { this.fromString(value); } } - _createClass(Decimal, [{ key: "m", get: function get() { if (this.sign === 0) { return 0; } else if (this.layer === 0) { - var exp = Math.floor(Math.log10(this.mag)); //handle special case 5e-324 - + var exp = Math.floor(Math.log10(this.mag)); + //handle special case 5e-324 var man; - if (this.mag === 5e-324) { man = 5; } else { man = this.mag / powerOf10(exp); } - return this.sign * man; } else if (this.layer === 1) { var residue = this.mag - Math.floor(this.mag); @@ -436,7 +411,6 @@ var Decimal = /*#__PURE__*/function () { } else { //don't even pretend mantissa is meaningful this.sign = Math.sign(value); - if (this.sign === 0) { this.layer = 0; this.exponent = 0; @@ -474,8 +448,8 @@ var Decimal = /*#__PURE__*/function () { } else { this.sign = value; } - } // Object.defineProperty(Decimal.prototype, "mantissa", { - + } + // Object.defineProperty(Decimal.prototype, "mantissa", { }, { key: "mantissa", get: function get() { @@ -514,23 +488,19 @@ var Decimal = /*#__PURE__*/function () { this.layer = 0; return this; } - if (this.layer === 0 && this.mag < 0) { //extract sign from negative mag at layer 0 this.mag = -this.mag; this.sign = -this.sign; - } //Handle shifting from layer 0 to negative layers. - - + } + //Handle shifting from layer 0 to negative layers. if (this.layer === 0 && this.mag < FIRST_NEG_LAYER) { this.layer += 1; this.mag = Math.log10(this.mag); return this; } - var absmag = Math.abs(this.mag); var signmag = Math.sign(this.mag); - if (absmag >= EXP_LIMIT) { this.layer += 1; this.mag = signmag * Math.log10(absmag); @@ -538,7 +508,6 @@ var Decimal = /*#__PURE__*/function () { } else { while (absmag < LAYER_DOWN && this.layer > 0) { this.layer -= 1; - if (this.layer === 0) { this.mag = Math.pow(10, this.mag); } else { @@ -547,7 +516,6 @@ var Decimal = /*#__PURE__*/function () { signmag = Math.sign(this.mag); } } - if (this.layer === 0) { if (this.mag < 0) { //extract sign from negative mag at layer 0 @@ -559,7 +527,6 @@ var Decimal = /*#__PURE__*/function () { } } } - return this; } }, { @@ -618,215 +585,181 @@ var Decimal = /*#__PURE__*/function () { value: function fromString(value) { var originalValue = value; var cached = Decimal.fromStringCache.get(originalValue); - if (cached !== undefined) { return this.fromDecimal(cached); } - { value = value.replace(",", ""); - } //Handle x^^^y format. - - + } + //Handle x^^^y format. var pentationparts = value.split("^^^"); - if (pentationparts.length === 2) { var _base = parseFloat(pentationparts[0]); - var _height = parseFloat(pentationparts[1]); - var heightparts = pentationparts[1].split(";"); var payload = 1; - if (heightparts.length === 2) { payload = parseFloat(heightparts[1]); - if (!isFinite(payload)) { payload = 1; } } - if (isFinite(_base) && isFinite(_height)) { var result = Decimal.pentate(_base, _height, payload); this.sign = result.sign; this.layer = result.layer; this.mag = result.mag; - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } - } //Handle x^^y format. - - + } + //Handle x^^y format. var tetrationparts = value.split("^^"); - if (tetrationparts.length === 2) { var _base2 = parseFloat(tetrationparts[0]); - var _height2 = parseFloat(tetrationparts[1]); - var _heightparts = tetrationparts[1].split(";"); - var _payload = 1; - if (_heightparts.length === 2) { _payload = parseFloat(_heightparts[1]); - if (!isFinite(_payload)) { _payload = 1; } } - if (isFinite(_base2) && isFinite(_height2)) { var _result = Decimal.tetrate(_base2, _height2, _payload); - this.sign = _result.sign; this.layer = _result.layer; this.mag = _result.mag; - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } - } //Handle x^y format. - - + } + //Handle x^y format. var powparts = value.split("^"); - if (powparts.length === 2) { var _base3 = parseFloat(powparts[0]); - var _exponent = parseFloat(powparts[1]); - if (isFinite(_base3) && isFinite(_exponent)) { var _result2 = Decimal.pow(_base3, _exponent); - this.sign = _result2.sign; this.layer = _result2.layer; this.mag = _result2.mag; - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } - } //Handle various cases involving it being a Big Number. - - - value = value.trim().toLowerCase(); //handle X PT Y format. - + } + //Handle various cases involving it being a Big Number. + value = value.trim().toLowerCase(); + //handle X PT Y format. var base; var height; var ptparts = value.split("pt"); - if (ptparts.length === 2) { base = 10; height = parseFloat(ptparts[0]); ptparts[1] = ptparts[1].replace("(", ""); ptparts[1] = ptparts[1].replace(")", ""); - var _payload2 = parseFloat(ptparts[1]); - if (!isFinite(_payload2)) { _payload2 = 1; } - if (isFinite(base) && isFinite(height)) { var _result3 = Decimal.tetrate(base, height, _payload2); - this.sign = _result3.sign; this.layer = _result3.layer; this.mag = _result3.mag; - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } - } //handle XpY format (it's the same thing just with p). - - + } + //handle XpY format (it's the same thing just with p). ptparts = value.split("p"); - if (ptparts.length === 2) { base = 10; height = parseFloat(ptparts[0]); ptparts[1] = ptparts[1].replace("(", ""); ptparts[1] = ptparts[1].replace(")", ""); - var _payload3 = parseFloat(ptparts[1]); - if (!isFinite(_payload3)) { _payload3 = 1; } - if (isFinite(base) && isFinite(height)) { var _result4 = Decimal.tetrate(base, height, _payload3); - this.sign = _result4.sign; this.layer = _result4.layer; this.mag = _result4.mag; - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } } - + //handle XFY format + ptparts = value.split("f"); + if (ptparts.length === 2) { + base = 10; + ptparts[0] = ptparts[0].replace("(", ""); + ptparts[0] = ptparts[0].replace(")", ""); + var _payload4 = parseFloat(ptparts[0]); + ptparts[1] = ptparts[1].replace("(", ""); + ptparts[1] = ptparts[1].replace(")", ""); + height = parseFloat(ptparts[1]); + if (!isFinite(_payload4)) { + _payload4 = 1; + } + if (isFinite(base) && isFinite(height)) { + var _result5 = Decimal.tetrate(base, height, _payload4); + this.sign = _result5.sign; + this.layer = _result5.layer; + this.mag = _result5.mag; + if (Decimal.fromStringCache.maxSize >= 1) { + Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); + } + return this; + } + } var parts = value.split("e"); - var ecount = parts.length - 1; //Handle numbers that are exactly floats (0 or 1 es). - + var ecount = parts.length - 1; + //Handle numbers that are exactly floats (0 or 1 es). if (ecount === 0) { var numberAttempt = parseFloat(value); - if (isFinite(numberAttempt)) { this.fromNumber(numberAttempt); - if (Decimal.fromStringCache.size >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } } else if (ecount === 1) { //Very small numbers ("2e-3000" and so on) may look like valid floats but round to 0. var _numberAttempt = parseFloat(value); - if (isFinite(_numberAttempt) && _numberAttempt !== 0) { this.fromNumber(_numberAttempt); - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } - } //Handle new (e^N)X format. - - + } + //Handle new (e^N)X format. var newparts = value.split("e^"); - if (newparts.length === 2) { this.sign = 1; - if (newparts[0].charAt(0) == "-") { this.sign = -1; } - var layerstring = ""; - for (var i = 0; i < newparts[1].length; ++i) { var chrcode = newparts[1].charCodeAt(i); - if (chrcode >= 43 && chrcode <= 57 || chrcode === 101) { //is "0" to "9" or "+" or "-" or "." or "e" (or "," or "/") layerstring += newparts[1].charAt(i); @@ -835,93 +768,76 @@ var Decimal = /*#__PURE__*/function () { this.layer = parseFloat(layerstring); this.mag = parseFloat(newparts[1].substr(i + 1)); this.normalize(); - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } } } - if (ecount < 1) { this.sign = 0; this.layer = 0; this.mag = 0; - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } - var mantissa = parseFloat(parts[0]); - if (mantissa === 0) { this.sign = 0; this.layer = 0; this.mag = 0; - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } - - var exponent = parseFloat(parts[parts.length - 1]); //handle numbers like AeBeC and AeeeeBeC - + var exponent = parseFloat(parts[parts.length - 1]); + //handle numbers like AeBeC and AeeeeBeC if (ecount >= 2) { var me = parseFloat(parts[parts.length - 2]); - if (isFinite(me)) { exponent *= Math.sign(me); exponent += f_maglog10(me); } - } //Handle numbers written like eee... (N es) X - - + } + //Handle numbers written like eee... (N es) X if (!isFinite(mantissa)) { this.sign = parts[0] === "-" ? -1 : 1; this.layer = ecount; this.mag = exponent; - } //Handle numbers written like XeY + } + //Handle numbers written like XeY else if (ecount === 1) { this.sign = Math.sign(mantissa); - this.layer = 1; //Example: 2e10 is equal to 10^log10(2e10) which is equal to 10^(10+log10(2)) - + this.layer = 1; + //Example: 2e10 is equal to 10^log10(2e10) which is equal to 10^(10+log10(2)) this.mag = exponent + Math.log10(Math.abs(mantissa)); - } //Handle numbers written like Xeee... (N es) Y + } + //Handle numbers written like Xeee... (N es) Y else { this.sign = Math.sign(mantissa); this.layer = ecount; - if (ecount === 2) { - var _result5 = Decimal.mul(FC(1, 2, exponent), D(mantissa)); - - this.sign = _result5.sign; - this.layer = _result5.layer; - this.mag = _result5.mag; - + var _result6 = Decimal.mul(FC(1, 2, exponent), D(mantissa)); + this.sign = _result6.sign; + this.layer = _result6.layer; + this.mag = _result6.mag; if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } else { //at eee and above, mantissa is too small to be recognizable! this.mag = exponent; } } - this.normalize(); - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } }, { @@ -930,15 +846,12 @@ var Decimal = /*#__PURE__*/function () { if (value instanceof Decimal) { return this.fromDecimal(value); } - if (typeof value === "number") { return this.fromNumber(value); } - if (typeof value === "string") { return this.fromString(value); } - this.sign = 0; this.layer = 0; this.mag = 0; @@ -950,7 +863,6 @@ var Decimal = /*#__PURE__*/function () { if (!Number.isFinite(this.layer)) { return Number.NaN; } - if (this.layer === 0) { return this.sign * this.mag; } else if (this.layer === 1) { @@ -967,11 +879,9 @@ var Decimal = /*#__PURE__*/function () { if (isNaN(this.m)) { return Number.NaN; } - if (this.m === 0) { return 0; } - return decimalPlaces(this.m, places); } }, { @@ -981,11 +891,9 @@ var Decimal = /*#__PURE__*/function () { if (isNaN(this.mag)) { return Number.NaN; } - if (this.mag === 0) { return 0; } - return decimalPlaces(this.mag, places); } }, { @@ -994,16 +902,13 @@ 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) { return this.sign === 1 ? "Infinity" : "-Infinity"; } - if (this.layer === 0) { if (this.mag < 1e21 && this.mag > 1e-7 || this.mag === 0) { return (this.sign * this.mag).toString(); } - return this.m + "e" + this.e; } else if (this.layer === 1) { return this.m + "e" + this.e; @@ -1022,7 +927,6 @@ var Decimal = /*#__PURE__*/function () { if (this.layer === 0) { return (this.sign * this.mag).toExponential(places); } - return this.toStringWithDecimalPlaces(places); } }, { @@ -1031,7 +935,6 @@ var Decimal = /*#__PURE__*/function () { if (this.layer === 0) { return (this.sign * this.mag).toFixed(places); } - return this.toStringWithDecimalPlaces(places); } }, { @@ -1040,11 +943,9 @@ var Decimal = /*#__PURE__*/function () { if (this.e <= -7) { return this.toExponential(places - 1); } - if (places > this.e) { return this.toFixed(places - this.exponent - 1); } - return this.toExponential(places - 1); } }, { @@ -1064,7 +965,6 @@ var Decimal = /*#__PURE__*/function () { if (this.mag < 1e21 && this.mag > 1e-7 || this.mag === 0) { return (this.sign * this.mag).toFixed(places); } - return decimalPlaces(this.m, places) + "e" + decimalPlaces(this.e, places); } else if (this.layer === 1) { return decimalPlaces(this.m, places) + "e" + decimalPlaces(this.e, places); @@ -1096,10 +996,10 @@ var Decimal = /*#__PURE__*/function () { key: "negated", value: function negated() { return this.neg(); - } // public sign () { + } + // public sign () { // return this.sign; // } - }, { key: "sgn", value: function sgn() { @@ -1111,11 +1011,9 @@ var Decimal = /*#__PURE__*/function () { if (this.mag < 0) { return Decimal.dZero; } - if (this.layer === 0) { return FC(this.sign, 0, Math.round(this.mag)); } - return this; } }, { @@ -1124,11 +1022,9 @@ var Decimal = /*#__PURE__*/function () { if (this.mag < 0) { return Decimal.dZero; } - if (this.layer === 0) { return FC(this.sign, 0, Math.floor(this.mag)); } - return this; } }, { @@ -1137,11 +1033,9 @@ var Decimal = /*#__PURE__*/function () { if (this.mag < 0) { return Decimal.dZero; } - if (this.layer === 0) { return FC(this.sign, 0, Math.ceil(this.mag)); } - return this; } }, { @@ -1150,47 +1044,39 @@ var Decimal = /*#__PURE__*/function () { if (this.mag < 0) { return Decimal.dZero; } - if (this.layer === 0) { return FC(this.sign, 0, Math.trunc(this.mag)); } - return this; } }, { key: "add", value: function add(value) { - var decimal = D(value); //inf/nan check - + var decimal = D(value); + //inf/nan check if (!Number.isFinite(this.layer)) { return this; } - if (!Number.isFinite(decimal.layer)) { return decimal; - } //Special case - if one of the numbers is 0, return the other number. - - + } + //Special case - if one of the numbers is 0, return the other number. if (this.sign === 0) { return decimal; } - if (decimal.sign === 0) { return this; - } //Special case - Adding a number to its negation produces 0, no matter how large. - - + } + //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) { return FC_NN(0, 0, 0); } - var a; - var b; //Special case: If one of the numbers is layer 2 or higher, just take the bigger number. - + var b; + //Special case: If one of the numbers is layer 2 or higher, just take the bigger number. if (this.layer >= 2 || decimal.layer >= 2) { return this.maxabs(decimal); } - if (Decimal.cmpabs(this, decimal) > 0) { a = this; b = decimal; @@ -1198,18 +1084,15 @@ var Decimal = /*#__PURE__*/function () { a = decimal; b = this; } - if (a.layer === 0 && b.layer === 0) { return Decimal.fromNumber(a.sign * a.mag + b.sign * b.mag); } - var layera = a.layer * Math.sign(a.mag); - var layerb = b.layer * Math.sign(b.mag); //If one of the numbers is 2+ layers higher than the other, just take the bigger number. - + var layerb = b.layer * Math.sign(b.mag); + //If one of the numbers is 2+ layers higher than the other, just take the bigger number. if (layera - layerb >= 2) { return a; } - if (layera === 0 && layerb === -1) { if (Math.abs(b.mag - Math.log10(a.mag)) > MAX_SIGNIFICANT_DIGITS) { return a; @@ -1219,26 +1102,20 @@ var Decimal = /*#__PURE__*/function () { return FC(Math.sign(mantissa), 1, b.mag + Math.log10(Math.abs(mantissa))); } } - if (layera === 1 && layerb === 0) { if (Math.abs(a.mag - Math.log10(b.mag)) > MAX_SIGNIFICANT_DIGITS) { return a; } else { var _magdiff = Math.pow(10, a.mag - Math.log10(b.mag)); - var _mantissa = b.sign + a.sign * _magdiff; - return FC(Math.sign(_mantissa), 1, Math.log10(b.mag) + Math.log10(Math.abs(_mantissa))); } } - if (Math.abs(a.mag - b.mag) > MAX_SIGNIFICANT_DIGITS) { return a; } else { var _magdiff2 = Math.pow(10, a.mag - b.mag); - var _mantissa2 = b.sign + a.sign * _magdiff2; - return FC(Math.sign(_mantissa2), 1, b.mag + Math.log10(Math.abs(_mantissa2))); } } @@ -1265,29 +1142,25 @@ var Decimal = /*#__PURE__*/function () { }, { key: "mul", value: function mul(value) { - var decimal = D(value); //inf/nan check - + var decimal = D(value); + //inf/nan check if (!Number.isFinite(this.layer)) { return this; } - if (!Number.isFinite(decimal.layer)) { return decimal; - } //Special case - if one of the numbers is 0, return 0. - - + } + //Special case - if one of the numbers is 0, return 0. if (this.sign === 0 || decimal.sign === 0) { return FC_NN(0, 0, 0); - } //Special case - Multiplying a number by its own reciprocal yields +/- 1, no matter how large. - - + } + //Special case - Multiplying a number by its own reciprocal yields +/- 1, no matter how large. if (this.layer === decimal.layer && this.mag === -decimal.mag) { return FC_NN(this.sign * decimal.sign, 0, 1); } - var a; - var b; //Which number is bigger in terms of its multiplicative distance from 1? - + 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; @@ -1295,35 +1168,27 @@ var Decimal = /*#__PURE__*/function () { a = decimal; b = this; } - if (a.layer === 0 && b.layer === 0) { return Decimal.fromNumber(a.sign * b.sign * a.mag * b.mag); - } //Special case: If one of the numbers is layer 3 or higher or one of the numbers is 2+ layers bigger than the other, just take the bigger number. - - + } + //Special case: If one of the numbers is layer 3 or higher or one of the numbers is 2+ layers bigger than the other, just take the bigger number. if (a.layer >= 3 || a.layer - b.layer >= 2) { return FC(a.sign * b.sign, a.layer, a.mag); } - if (a.layer === 1 && b.layer === 0) { return FC(a.sign * b.sign, 1, a.mag + Math.log10(b.mag)); } - if (a.layer === 1 && b.layer === 1) { return FC(a.sign * b.sign, 1, a.mag + b.mag); } - if (a.layer === 2 && b.layer === 1) { var newmag = FC(Math.sign(a.mag), a.layer - 1, Math.abs(a.mag)).add(FC(Math.sign(b.mag), b.layer - 1, Math.abs(b.mag))); return FC(a.sign * b.sign, newmag.layer + 1, newmag.sign * newmag.mag); } - if (a.layer === 2 && b.layer === 2) { var _newmag = FC(Math.sign(a.mag), a.layer - 1, Math.abs(a.mag)).add(FC(Math.sign(b.mag), b.layer - 1, Math.abs(b.mag))); - return FC(a.sign * b.sign, _newmag.layer + 1, _newmag.sign * _newmag.mag); } - throw Error("Bad arguments to mul: " + this + ", " + value); } }, { @@ -1378,23 +1243,53 @@ var Decimal = /*#__PURE__*/function () { value: function reciprocate() { return this.recip(); } + //Taken from OmegaNum.js, with a couple touch-ups + //"Truncated division" modulo, like JavaScript's % + }, { + key: "mod", + value: function mod(value) { + var decimal = D(value).abs(); + if (decimal.eq(Decimal.dZero)) return Decimal.dZero; + 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 + if (isFinite(num_this) && isFinite(num_decimal) && num_this != 0 && num_decimal != 0) { + return new Decimal(num_this % num_decimal); + } + if (this.sub(decimal).eq(this)) { + //decimal is too small to register to this + return Decimal.dZero; + } + if (decimal.sub(this).eq(decimal)) { + //this is too small to register to decimal + return this; + } + if (this.sign == -1) return this.abs().mod(decimal).neg(); + return this.sub(this.div(decimal).floor().mul(decimal)); + } + }, { + key: "modulo", + value: function modulo(value) { + return this.mod(value); + } + }, { + key: "modular", + value: function modular(value) { + return this.mod(value); + } /** * -1 for less than value, 0 for equals value, 1 for greater than value */ - }, { key: "cmp", value: function cmp(value) { var decimal = D(value); - if (this.sign > decimal.sign) { return 1; } - if (this.sign < decimal.sign) { return -1; } - return this.sign * this.cmpabs(value); } }, { @@ -1403,23 +1298,18 @@ var Decimal = /*#__PURE__*/function () { var decimal = D(value); var layera = this.mag > 0 ? this.layer : -this.layer; var layerb = decimal.mag > 0 ? decimal.layer : -decimal.layer; - if (layera > layerb) { return 1; } - if (layera < layerb) { return -1; } - if (this.mag > decimal.mag) { return 1; } - if (this.mag < decimal.mag) { return -1; } - return 0; } }, { @@ -1438,11 +1328,9 @@ var Decimal = /*#__PURE__*/function () { function isFinite() { return _isFinite2.apply(this, arguments); } - isFinite.toString = function () { return _isFinite2.toString(); }; - return isFinite; }(function () { return isFinite(this.sign) && isFinite(this.layer) && isFinite(this.mag); @@ -1543,37 +1431,29 @@ var Decimal = /*#__PURE__*/function () { * For example, if you put in 1e-9, then any number closer to the * larger number than (larger number)*1e-9 will be considered equal. */ - }, { key: "eq_tolerance", value: function eq_tolerance(value, tolerance) { var decimal = D(value); // https://stackoverflow.com/a/33024979 - if (tolerance == null) { tolerance = 1e-7; - } //Numbers that are too far away are never close. - - + } + //Numbers that are too far away are never close. if (this.sign !== decimal.sign) { return false; } - if (Math.abs(this.layer - decimal.layer) > 1) { return false; - } // return abs(a-b) <= tolerance * max(abs(a), abs(b)) - - + } + // return abs(a-b) <= tolerance * max(abs(a), abs(b)) var magA = this.mag; var magB = decimal.mag; - if (this.layer > decimal.layer) { magB = f_maglog10(magB); } - if (this.layer < decimal.layer) { magA = f_maglog10(magA); } - return Math.abs(magA - magB) <= tolerance * Math.max(Math.abs(magA), Math.abs(magB)); } }, { @@ -1621,7 +1501,6 @@ var Decimal = /*#__PURE__*/function () { if (this.lt(Decimal.dZero)) { return Decimal.dZero; } - return this.log10(); } }, { @@ -1650,21 +1529,17 @@ var Decimal = /*#__PURE__*/function () { key: "log", value: function log(base) { base = D(base); - if (this.sign <= 0) { return Decimal.dNaN; } - if (base.sign <= 0) { return Decimal.dNaN; } - if (base.sign === 1 && base.layer === 0 && base.mag === 1) { return Decimal.dNaN; } else if (this.layer === 0 && base.layer === 0) { return FC(this.sign, 0, Math.log(this.mag) / Math.log(base.mag)); } - return Decimal.div(this.log10(), base.log10()); } }, { @@ -1707,39 +1582,32 @@ var Decimal = /*#__PURE__*/function () { value: function pow(value) { var decimal = D(value); var a = this; - var b = decimal; //special case: if a is 0, then return 0 (UNLESS b is 0, then return 1) - + var b = 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; - } //special case: if a is 1, then return 1 - - + } + //special case: if a is 1, then return 1 if (a.sign === 1 && a.layer === 0 && a.mag === 1) { return a; - } //special case: if b is 0, then return 1 - - + } + //special case: if b is 0, then return 1 if (b.sign === 0) { return FC_NN(1, 0, 1); - } //special case: if b is 1, then return a - - + } + //special case: if b is 1, then return a if (b.sign === 1 && b.layer === 0 && b.mag === 1) { return a; } - var result = a.absLog10().mul(b).pow10(); - if (this.sign === -1) { if (Math.abs(b.toNumber() % 2) % 2 === 1) { return result.neg(); } else if (Math.abs(b.toNumber() % 2) % 2 === 0) { return result; } - return Decimal.dNaN; } - return result; } }, { @@ -1754,13 +1622,11 @@ var Decimal = /*#__PURE__*/function () { */ if (!Number.isFinite(this.layer) || !Number.isFinite(this.mag)) { return Decimal.dNaN; - } - - var a = this; //handle layer 0 case - if no precision is lost just use Math.pow, else promote one layer - + } + var a = 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); - if (Number.isFinite(newmag) && Math.abs(newmag) >= 0.1) { return FC(1, 0, newmag); } else { @@ -1770,18 +1636,15 @@ var Decimal = /*#__PURE__*/function () { a = FC_NN(a.sign, a.layer + 1, Math.log10(a.mag)); } } - } //handle all 4 layer 1+ cases individually - - + } + //handle all 4 layer 1+ cases individually if (a.sign > 0 && a.mag >= 0) { return FC(a.sign, a.layer + 1, a.mag); } - if (a.sign < 0 && a.mag >= 0) { return FC(-a.sign, a.layer + 1, -a.mag); - } //both the negative mag cases are identical: one +/- rounding error - - + } + //both the negative mag cases are identical: one +/- rounding error return Decimal.dOne; } }, { @@ -1807,8 +1670,8 @@ var Decimal = /*#__PURE__*/function () { } else { return Decimal.exp(this); } - } //from HyperCalc source code - + } + //from HyperCalc source code }, { key: "gamma", value: function gamma() { @@ -1818,10 +1681,8 @@ var Decimal = /*#__PURE__*/function () { if (this.lt(FC_NN(1, 0, 24))) { return Decimal.fromNumber(f_gamma(this.sign * this.mag)); } - var t = this.mag - 1; var l = 0.9189385332046727; //0.5*Math.log(2*Math.PI) - l = l + (t + 0.5) * Math.log(t); l = l - t; var n2 = t * t; @@ -1829,21 +1690,17 @@ var Decimal = /*#__PURE__*/function () { var lm = 12 * np; var adj = 1 / lm; var l2 = l + adj; - if (l2 === l) { return Decimal.exp(l); } - l = l2; np = np * n2; lm = 360 * np; adj = 1 / lm; l2 = l - adj; - if (l2 === l) { return Decimal.exp(l); } - l = l2; np = np * n2; lm = 1260 * np; @@ -1871,7 +1728,6 @@ var Decimal = /*#__PURE__*/function () { if (this.mag < 0) { return Decimal.dOne; } - if (this.layer === 0 && this.mag <= 709.7) { return Decimal.fromNumber(Math.exp(this.sign * this.mag)); } else if (this.layer === 0) { @@ -1910,46 +1766,41 @@ var Decimal = /*#__PURE__*/function () { key: "cbrt", value: function cbrt() { return this.pow(1 / 3); - } //Tetration/tetrate: The result of exponentiating 'this' to 'this' 'height' times in a row. https://en.wikipedia.org/wiki/Tetration + } + //Tetration/tetrate: The result of exponentiating 'this' to 'this' 'height' times in a row. https://en.wikipedia.org/wiki/Tetration //If payload != 1, then this is 'iterated exponentiation', the result of exping (payload) to base (this) (height) times. https://andydude.github.io/tetration/archives/tetration2/ident.html //Works with negative and positive real heights. - }, { key: "tetrate", value: function tetrate() { 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; //x^^1 == x if (height === 1) { return Decimal.pow(this, payload); - } //x^^0 == 1 - - + } + //x^^0 == 1 if (height === 0) { return new Decimal(payload); - } //1^^x == 1 - - + } + //1^^x == 1 if (this.eq(Decimal.dOne)) { return Decimal.dOne; - } //-1^^x == -1 - - + } + //-1^^x == -1 if (this.eq(-1)) { return Decimal.pow(this, payload); } - if (height === Number.POSITIVE_INFINITY) { - var this_num = this.toNumber(); //within the convergence range? - + var this_num = this.toNumber(); + //within the convergence range? if (this_num <= 1.44466786100976613366 && this_num >= 0.06598803584531253708) { //hotfix for the very edge of the number range not being handled properly if (this_num > 1.444667861009099) { return Decimal.fromNumber(Math.E); - } //Formula for infinite height power tower. - - + } + //Formula for infinite height power tower. var negln = Decimal.ln(this).neg(); return negln.lambertw().div(negln); } else if (this_num > 1.44466786100976613366) { @@ -1961,259 +1812,232 @@ var Decimal = /*#__PURE__*/function () { //this_num < 0: quickly becomes a complex number return Decimal.dNaN; } - } //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 + } + //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 //using the linear approximation for height (TODO: don't know a better way to calculate it ATM, but it wouldn't surprise me if it's just NaN) - - if (this.eq(Decimal.dZero)) { var result = Math.abs((height + 1) % 2); - if (result > 1) { result = 2 - result; } - return Decimal.fromNumber(result); } - if (height < 0) { - return Decimal.iteratedlog(payload, this, -height); + return Decimal.iteratedlog(payload, this, -height, linear); } - payload = D(payload); var oldheight = height; height = Math.trunc(height); var fracheight = oldheight - height; - - if (this.gt(Decimal.dZero) && this.lte(1.44466786100976613366)) { + 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) { var old_payload = payload; - payload = this.pow(payload); //stop early if we converge - + payload = this.pow(payload); + //stop early if we converge if (old_payload.eq(payload)) { return payload; } } - - if (fracheight != 0) { + if (fracheight != 0 || oldheight > 10000) { var next_payload = this.pow(payload); - return payload.mul(1 - fracheight).add(next_payload.mul(fracheight)); + 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)); + } } - return payload; - } //TODO: base < 0, but it's hard for me to reason about (probably all non-integer heights are NaN automatically?) - - + } + //TODO: base < 0, but it's hard for me to reason about (probably all non-integer heights are NaN automatically?) if (fracheight !== 0) { if (payload.eq(Decimal.dOne)) { + //If (linear), use linear approximation even for bases <= 10 //TODO: for bases above 10, revert to old linear approximation until I can think of something better - if (this.gt(10)) { + if (this.gt(10) || linear) { payload = this.pow(fracheight); } else { - payload = Decimal.fromNumber(Decimal.tetrate_critical(this.toNumber(), fracheight)); //TODO: until the critical section grid can handle numbers below 2, scale them to the base + payload = Decimal.fromNumber(Decimal.tetrate_critical(this.toNumber(), fracheight)); + //TODO: until the critical section grid can handle numbers below 2, scale them to the base //TODO: maybe once the critical section grid has very large bases, this math can be appropriate for them too? I'll think about it - if (this.lt(2)) { payload = payload.sub(1).mul(this.minus(1)).plus(1); } } } else { if (this.eq(10)) { - payload = payload.layeradd10(fracheight); + payload = payload.layeradd10(fracheight, linear); } else { - payload = payload.layeradd(fracheight, this); + payload = payload.layeradd(fracheight, this, linear); } } } - for (var _i = 0; _i < height; ++_i) { - payload = this.pow(payload); //bail if we're NaN - + payload = this.pow(payload); + //bail if we're NaN if (!isFinite(payload.layer) || !isFinite(payload.mag)) { return payload.normalize(); - } //shortcut - - + } + //shortcut if (payload.layer - this.layer > 3) { return FC_NN(payload.sign, payload.layer + (height - _i - 1), payload.mag); - } //give up after 10000 iterations if nothing is happening - - + } + //give up after 10000 iterations if nothing is happening if (_i > 10000) { return payload; } } - return payload; - } //iteratedexp/iterated exponentiation: - all cases handled in tetrate, so just call it - + } + //iteratedexp/iterated exponentiation: - all cases handled in tetrate, so just call it }, { key: "iteratedexp", value: function iteratedexp() { 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); - return this.tetrate(height, payload); - } //iterated log/repeated log: The result of applying log(base) 'times' times in a row. Approximately equal to subtracting (times) from the number's slog representation. Equivalent to tetrating to a negative height. + var linear = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + return this.tetrate(height, payload, linear); + } + //iterated log/repeated log: The result of applying log(base) 'times' times in a row. Approximately equal to subtracting (times) from the number's slog representation. Equivalent to tetrating to a negative height. //Works with negative and positive real heights. - }, { key: "iteratedlog", value: function iteratedlog() { var base = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 10; var times = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; - + var linear = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; if (times < 0) { - return Decimal.tetrate(base, -times, this); + return Decimal.tetrate(base, -times, this, linear); } - base = D(base); var result = Decimal.fromDecimal(this); var fulltimes = times; times = Math.trunc(times); var fraction = fulltimes - times; - if (result.layer - base.layer > 3) { var layerloss = Math.min(times, result.layer - base.layer - 3); times -= layerloss; result.layer -= layerloss; } - for (var i = 0; i < times; ++i) { - result = result.log(base); //bail if we're NaN - + result = result.log(base); + //bail if we're NaN if (!isFinite(result.layer) || !isFinite(result.mag)) { return result.normalize(); - } //give up after 10000 iterations if nothing is happening - - + } + //give up after 10000 iterations if nothing is happening if (i > 10000) { return result; } - } //handle fractional part - - + } + //handle fractional part if (fraction > 0 && fraction < 1) { if (base.eq(10)) { - result = result.layeradd10(-fraction); + result = result.layeradd10(-fraction, linear); } else { - result = result.layeradd(-fraction, base); + result = result.layeradd(-fraction, base, linear); } } - return result; - } //Super-logarithm, one of tetration's inverses, tells you what size power tower you'd have to tetrate base to to get number. By definition, will never be higher than 1.8e308 in break_eternity.js, since a power tower 1.8e308 numbers tall is the largest representable number. + } + //Super-logarithm, one of tetration's inverses, tells you what size power tower you'd have to tetrate base to to get number. By definition, will never be higher than 1.8e308 in break_eternity.js, since a power tower 1.8e308 numbers tall is the largest representable number. // https://en.wikipedia.org/wiki/Super-logarithm // NEW: Accept a number of iterations, and use binary search to, after making an initial guess, hone in on the true value, assuming tetration as the ground truth. - }, { key: "slog", value: function slog() { var base = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 10; var iterations = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100; + var linear = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; var step_size = 0.001; var has_changed_directions_once = false; var previously_rose = false; - var result = this.slog_internal(base).toNumber(); - + var result = this.slog_internal(base, linear).toNumber(); for (var i = 1; i < iterations; ++i) { - var new_decimal = new Decimal(base).tetrate(result); + var new_decimal = new Decimal(base).tetrate(result, Decimal.dOne, linear); var currently_rose = new_decimal.gt(this); - if (i > 1) { if (previously_rose != currently_rose) { has_changed_directions_once = true; } } - previously_rose = currently_rose; - if (has_changed_directions_once) { step_size /= 2; } else { step_size *= 2; } - step_size = Math.abs(step_size) * (currently_rose ? -1 : 1); result += step_size; - if (step_size === 0) { break; } } - return Decimal.fromNumber(result); } }, { key: "slog_internal", value: function slog_internal() { var base = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 10; - base = D(base); //special cases: + var linear = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + base = D(base); + //special cases: //slog base 0 or lower is NaN - if (base.lte(Decimal.dZero)) { return Decimal.dNaN; - } //slog base 1 is NaN - - + } + //slog base 1 is NaN if (base.eq(Decimal.dOne)) { return Decimal.dNaN; - } //need to handle these small, wobbling bases specially - - + } + //need to handle these small, wobbling bases specially if (base.lt(Decimal.dOne)) { if (this.eq(Decimal.dOne)) { return Decimal.dZero; } - if (this.eq(Decimal.dZero)) { return Decimal.dNegOne; - } //0 < this < 1: ambiguous (happens multiple times) + } + //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; - } //slog_n(0) is -1 - - + } + //slog_n(0) is -1 if (this.mag < 0 || this.eq(Decimal.dZero)) { return Decimal.dNegOne; } - var result = 0; var copy = Decimal.fromDecimal(this); - if (copy.layer - base.layer > 3) { var layerloss = copy.layer - base.layer - 3; result += layerloss; copy.layer -= layerloss; } - for (var i = 0; i < 100; ++i) { if (copy.lt(Decimal.dZero)) { copy = Decimal.pow(base, copy); result -= 1; } else if (copy.lte(Decimal.dOne)) { - return Decimal.fromNumber(result + Decimal.slog_critical(base.toNumber(), copy.toNumber())); + if (linear) return Decimal.fromNumber(result + copy.toNumber() - 1);else return Decimal.fromNumber(result + Decimal.slog_critical(base.toNumber(), copy.toNumber())); } else { result += 1; copy = Decimal.log(copy, base); } } - return Decimal.fromNumber(result); - } //background info and tables of values for critical functions taken here: https://github.com/Patashu/break_eternity.js/issues/22 - + } + //background info and tables of values for critical functions taken here: https://github.com/Patashu/break_eternity.js/issues/22 }, { key: "layeradd10", - value: //Function for adding/removing layers from a Decimal, even fractional layers (e.g. its slog10 representation). + value: + //Function for adding/removing layers from a Decimal, even fractional layers (e.g. its slog10 representation). //Moved this over to use the same critical section as tetrate/slog. function layeradd10(diff) { + var linear = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; diff = Decimal.fromValue_noAlloc(diff).toNumber(); var result = Decimal.fromDecimal(this); - if (diff >= 1) { //bug fix: if result is very smol (mag < 0, layer > 0) turn it into 0 first if (result.mag < 0 && result.layer > 0) { @@ -2225,87 +2049,75 @@ var Decimal = /*#__PURE__*/function () { result.sign = 1; result.mag = -result.mag; } - var layeradd = Math.trunc(diff); diff -= layeradd; result.layer += layeradd; } - if (diff <= -1) { var _layeradd = Math.trunc(diff); - diff -= _layeradd; result.layer += _layeradd; - if (result.layer < 0) { for (var i = 0; i < 100; ++i) { result.layer++; result.mag = Math.log10(result.mag); - if (!isFinite(result.mag)) { //another bugfix: if we hit -Infinity mag, then we should return negative infinity, not 0. 0.layeradd10(-1) h its this if (result.sign === 0) { result.sign = 1; - } //also this, for 0.layeradd10(-2) - - + } + //also this, for 0.layeradd10(-2) if (result.layer < 0) { result.layer = 0; } - return result.normalize(); } - if (result.layer >= 0) { break; } } } } - while (result.layer < 0) { result.layer++; result.mag = Math.log10(result.mag); - } //bugfix: before we normalize: if we started with 0, we now need to manually fix a layer ourselves! - - + } + //bugfix: before we normalize: if we started with 0, we now need to manually fix a layer ourselves! if (result.sign === 0) { result.sign = 1; - if (result.mag === 0 && result.layer >= 1) { result.layer -= 1; result.mag = 1; } } - - result.normalize(); //layeradd10: like adding 'diff' to the number's slog(base) representation. Very similar to tetrate base 10 and iterated log base 10. Also equivalent to adding a fractional amount to the number's layer in its break_eternity.js representation. - + result.normalize(); + //layeradd10: like adding 'diff' to the number's slog(base) representation. Very similar to tetrate base 10 and iterated log base 10. Also equivalent to adding a fractional amount to the number's layer in its break_eternity.js representation. if (diff !== 0) { - return result.layeradd(diff, 10); //safe, only calls positive height 1 payload tetration, slog and log + return result.layeradd(diff, 10, linear); //safe, only calls positive height 1 payload tetration, slog and log } return result; - } //layeradd: like adding 'diff' to the number's slog(base) representation. Very similar to tetrate base 'base' and iterated log base 'base'. - + } + //layeradd: like adding 'diff' to the number's slog(base) representation. Very similar to tetrate base 'base' and iterated log base 'base'. }, { 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 slogdest = slogthis + diff; - if (slogdest >= 0) { - return Decimal.tetrate(base, slogdest); + return Decimal.tetrate(base, slogdest, Decimal.dOne, linear); } else if (!Number.isFinite(slogdest)) { return Decimal.dNaN; } else if (slogdest >= -1) { - return Decimal.log(Decimal.tetrate(base, slogdest + 1), base); + return Decimal.log(Decimal.tetrate(base, slogdest + 1, Decimal.dOne, linear), base); } else { - return Decimal.log(Decimal.log(Decimal.tetrate(base, slogdest + 2), base), base); + return Decimal.log(Decimal.log(Decimal.tetrate(base, slogdest + 2, Decimal.dOne, linear), base), base); } - } //The Lambert W function, also called the omega function or product logarithm, is the solution W(x) === x*e^x. + } + //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 //Some special values, for testing: https://en.wikipedia.org/wiki/Lambert_W_function#Special_values - }, { key: "lambertw", value: function lambertw() { @@ -2320,78 +2132,346 @@ var Decimal = /*#__PURE__*/function () { } else if (this.layer === 2) { return d_lambertw(this); } - if (this.layer >= 3) { return FC_NN(this.sign, this.layer - 1, this.mag); } - throw "Unhandled behavior in lambertw()"; - } //The super square-root function - what number, tetrated to height 2, equals this? + } + //The super square-root function - what number, tetrated to height 2, equals this? //Other sroots are possible to calculate probably through guess and check methods, this one is easy though. // https://en.wikipedia.org/wiki/Tetration#Super-root - }, { key: "ssqrt", value: function ssqrt() { if (this.sign == 1 && this.layer >= 3) { return FC_NN(this.sign, this.layer - 1, this.mag); } - var lnx = this.ln(); return lnx.div(lnx.lambertw()); - } //Pentation/pentate: The result of tetrating 'height' times in a row. An absurdly strong operator - Decimal.pentate(2, 4.28) and Decimal.pentate(10, 2.37) are already too huge for break_eternity.js! - // https://en.wikipedia.org/wiki/Pentation + } + //Super-root, one of tetration's inverses - what number, tetrated to height (height), equals this? + //Only works with the linear approximation, because I don't know the structure of non-linear tetrations for inputs < 1 + //TODO: Optimize this like how slog is optimized + }, { + key: "linear_sroot", + value: function linear_sroot(degree) { + //1st-degree super root just returns its input + if (degree == 1) { + return this; + } + if (this.eq(Decimal.dInf)) { + return Decimal.dInf; + } + if (!this.isFinite()) { + return Decimal.dNaN; + } + //ssqrt handles square super-root faster + if (degree == 2) { + try { + //ssqrt uses lambertw which throws an error if the number is too small + return this.ssqrt(); + } catch (_a) { + return Decimal.dNaN; + } + } + //Using linear approximation, x^^n = x^n if 0 < n < 1 + if (degree > 0 && degree < 1) { + return this.root(degree); + } + //Using the linear approximation, there actually is a single solution for super roots with -2 < degree <= -1 + if (degree > -2 && degree < -1) { + return Decimal.fromNumber(degree).add(2).pow(this.recip()); + } + //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; + } + //Infinite degree super-root is x^(1/x) between 1/e <= x <= e, undefined otherwise + if (degree == Number.POSITIVE_INFINITY) { + var this_num = this.toNumber(); + if (this_num < Math.E && this_num > _EXPN1) { + return this.pow(this.recip()); + } else { + return Decimal.dNaN; + } + } + //Special case: any super-root of 1 is 1 + if (this.eq(1)) { + return Decimal.dOne; + } + //TODO: base < 0 (It'll probably be NaN anyway) + if (this.lt(0)) { + return Decimal.dNaN; + } + //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; + } + //this > 1 + if (this.gt(1)) { + //Uses guess-and-check to find the super-root. + //If this > 10^^(degree), then the answer is under iteratedlog(10, degree - 1): for example, ssqrt(x) < log(x, 10) as long as x > 10^10, and linear_sroot(x, 3) < log(log(x, 10), 10) as long as x > 10^10^10 + //On the other hand, if this < 10^^(degree), then clearly the answer is less than 10 + //Since the answer could be a higher-layered number itself (whereas slog's maximum is 1.8e308), the guess-and-check is scaled to the layer of the upper bound, so the guess is set to the average of some higher-layer exponents of the bounds rather than the bounds itself (as taking plain averages on tetrational-scale numbers would go nowhere) + var upperBound = Decimal.dTen; + if (this.gte(Decimal.tetrate(10, degree, 1, true))) { + upperBound = this.iteratedlog(10, degree - 1, true); + } + if (degree <= 1) { + upperBound = this.root(degree); + } + var lower = Decimal.dZero; //This is zero rather than one because we might be on a higher layer, so the lower bound might actually some 10^10^10...^0 + var layer = upperBound.layer; + var upper = upperBound.iteratedlog(10, layer, true); + var previous = upper; + var guess = upper.div(2); + var loopGoing = true; + while (loopGoing) { + guess = lower.add(upper).div(2); + if (Decimal.iteratedexp(10, layer, guess, true).tetrate(degree, 1, true).gt(this)) upper = guess;else lower = guess; + if (guess.eq(previous)) loopGoing = false;else previous = guess; + } + return Decimal.iteratedexp(10, layer, guess, true); + } + //0 < this < 1 + else { + //A tetration of decimal degree can potentially have three different portions, as shown at https://www.desmos.com/calculator/ayvqks6mxa, which is a graph of x^^2.05: + //The portion where the function is increasing, extending from a minimum (which may be at x = 0 or at some x between 0 and 1) up to infinity (I'll call this the "increasing" range) + //The portion where the function is decreasing (I'll call this the "decreasing" range) + //A small, steep increasing portion very close to x = 0 (I'll call this the "zero" range) + //If ceiling(degree) is even, then the tetration will either be strictly increasing, or it will have the increasing and decreasing ranges, but not the zero range (because if ceiling(degree) is even, 0^^degree == 1). + //If ceiling(degree) is odd, then the tetration will either be strictly increasing, or it will have all three ranges (because if ceiling(degree) is odd, 0^^degree == 0). + //The existence of these ranges means that a super-root could potentially have two or three valid answers. + //Out of these, we'd prefer the increasing range value if it exists, otherwise we'll take the zero range value (it can't have a decreasing range value if it doesn't have an increasing range value) if the zero range exists. + //It's possible to identify which range that "this" is in: + //If the tetration is decreasing at that point, the point is in the decreasing range. + //If the tetration is increasing at that point and ceiling(degree) is even, the point is in the increasing range since there is no zero range. + //If the tetration is increasing at that point and ceiling(degree) is odd, look at the second derivative at that point. If the second derivative is positive, the point is in the increasing range. If the second derivative is negative, the point is the zero range. + //We need to find the local minimum (separates decreasing and increasing ranges) and the local maximum (separates zero and decreasing ranges). + //(stage) is which stage of the loop we're in: stage 1 is finding the minimum, stage 2 means we're between the stages, and stage 3 is finding the maximum. + //The boundary between the decreasing range and the zero range can be very small, so we want to use layer -1 numbers. Therefore, all numbers involved are log10(recip()) of their actual values. + var stage = 1; + var minimum = FC(1, 10, 1); + var maximum = FC(1, 10, 1); + var _lower = FC(1, 10, 1); //eeeeeeeee-10, which is effectively 0; I would use Decimal.dInf but its reciprocal is NaN + var _upper = FC(1, 1, -16); //~ 1 - 1e-16 + var prevspan = Decimal.dZero; + var difference = FC(1, 10, 1); + var _upperBound = _upper.pow10().recip(); + var distance = Decimal.dZero; + var prevPoint = _upperBound; + var nextPoint = _upperBound; + var evenDegree = Math.ceil(degree) % 2 == 0; + var range = 0; + var lastValid = FC(1, 10, 1); + var infLoopDetector = false; + var previousUpper = Decimal.dZero; + var decreasingFound = false; + while (stage < 4) { + if (stage == 2) { + //The minimum has been found. If ceiling(degree) is even, there's no zero range and thus no local maximum, so end the loop here. Otherwise, begin finding the maximum. + if (evenDegree) break;else { + _lower = FC(1, 10, 1); + _upper = minimum; + stage = 3; + difference = FC(1, 10, 1); + lastValid = FC(1, 10, 1); + } + } + infLoopDetector = false; + while (_upper.neq(_lower)) { + previousUpper = _upper; + if (_upper.pow10().recip().tetrate(degree, 1, true).eq(1) && _upper.pow10().recip().lt(0.4)) { + _upperBound = _upper.pow10().recip(); + prevPoint = _upper.pow10().recip(); + nextPoint = _upper.pow10().recip(); + distance = Decimal.dZero; + range = -1; //This would cause problems with degree < 1 in the linear approximation... but those are already covered as a special case + if (stage == 3) lastValid = _upper; + } else if (_upper.pow10().recip().tetrate(degree, 1, true).eq(_upper.pow10().recip()) && !evenDegree && _upper.pow10().recip().lt(0.4)) { + _upperBound = _upper.pow10().recip(); + prevPoint = _upper.pow10().recip(); + nextPoint = _upper.pow10().recip(); + distance = Decimal.dZero; + range = 0; + } else if (_upper.pow10().recip().tetrate(degree, 1, true).eq(_upper.pow10().recip().mul(2).tetrate(degree, 1, true))) { + //If the upper bound is closer to zero than the next point with a discernable tetration, so surely it's in whichever range is closest to zero? + //This won't happen in a strictly increasing tetration, as there x^^degree ~= x as x approaches zero + _upperBound = _upper.pow10().recip(); + prevPoint = Decimal.dZero; + nextPoint = _upperBound.mul(2); + distance = _upperBound; + if (evenDegree) range = -1;else range = 0; + } else { + //We want to use prevspan to find the "previous point" right before the upper bound and the "next point" right after the upper bound, as that will let us approximate derivatives + prevspan = _upper.mul(1.2e-16); + _upperBound = _upper.pow10().recip(); + prevPoint = _upper.add(prevspan).pow10().recip(); + distance = _upperBound.sub(prevPoint); + nextPoint = _upperBound.add(distance); + //...but it's of no use to us while its tetration is equal to upper's tetration, so widen the difference until it's not + //We add prevspan and subtract nextspan because, since upper is log10(recip(upper bound)), the upper bound gets smaller as upper gets larger and vice versa + while (prevPoint.tetrate(degree, 1, true).eq(_upperBound.tetrate(degree, 1, true)) || nextPoint.tetrate(degree, 1, true).eq(_upperBound.tetrate(degree, 1, true)) || prevPoint.gte(_upperBound) || nextPoint.lte(_upperBound)) { + prevspan = prevspan.mul(2); + prevPoint = _upper.add(prevspan).pow10().recip(); + distance = _upperBound.sub(prevPoint); + nextPoint = _upperBound.add(distance); + } + if (stage == 1 && nextPoint.tetrate(degree, 1, true).gt(_upperBound.tetrate(degree, 1, true)) && prevPoint.tetrate(degree, 1, true).gt(_upperBound.tetrate(degree, 1, true)) || stage == 3 && nextPoint.tetrate(degree, 1, true).lt(_upperBound.tetrate(degree, 1, true)) && prevPoint.tetrate(degree, 1, true).lt(_upperBound.tetrate(degree, 1, true))) { + lastValid = _upper; + } + if (nextPoint.tetrate(degree, 1, true).lt(_upperBound.tetrate(degree, 1, true))) { + //Derivative is negative, so we're in decreasing range + range = -1; + } else if (evenDegree) { + //No zero range, so we're in increasing range + range = 1; + } else if (stage == 3 && _upper.gt_tolerance(minimum, 1e-8)) { + //We're already below the minimum, so we can't be in range 1 + range = 0; + } else { + //Number imprecision has left the second derivative somewhat untrustworthy, so we need to expand the bounds to ensure it's correct + while (prevPoint.tetrate(degree, 1, true).eq_tolerance(_upperBound.tetrate(degree, 1, true), 1e-8) || nextPoint.tetrate(degree, 1, true).eq_tolerance(_upperBound.tetrate(degree, 1, true), 1e-8) || prevPoint.gte(_upperBound) || nextPoint.lte(_upperBound)) { + prevspan = prevspan.mul(2); + prevPoint = _upper.add(prevspan).pow10().recip(); + distance = _upperBound.sub(prevPoint); + nextPoint = _upperBound.add(distance); + } + if (nextPoint.tetrate(degree, 1, true).sub(_upperBound.tetrate(degree, 1, true)).lt(_upperBound.tetrate(degree, 1, true).sub(prevPoint.tetrate(degree, 1, true)))) { + //Second derivative is negative, so we're in zero range + range = 0; + } else { + //By process of elimination, we're in increasing range + range = 1; + } + } + } + if (range == -1) decreasingFound = true; + if (stage == 1 && range == 1 || stage == 3 && range != 0) { + //The upper bound is too high + if (_lower.eq(FC(1, 10, 1))) { + _upper = _upper.mul(2); + } else { + var cutOff = false; + if (infLoopDetector && (range == 1 && stage == 1 || range == -1 && stage == 3)) cutOff = true; //Avoids infinite loops from floating point imprecision + _upper = _upper.add(_lower).div(2); + if (cutOff) break; + } + } else { + if (_lower.eq(FC(1, 10, 1))) { + //We've now found an actual lower bound + _lower = _upper; + _upper = _upper.div(2); + } else { + //The upper bound is too low, meaning last time we decreased the upper bound, we should have gone to the other half of the new range instead + var _cutOff = false; + if (infLoopDetector && (range == 1 && stage == 1 || range == -1 && stage == 3)) _cutOff = true; //Avoids infinite loops from floating point imprecision + _lower = _lower.sub(difference); + _upper = _upper.sub(difference); + if (_cutOff) break; + } + } + if (_lower.sub(_upper).div(2).abs().gt(difference.mul(1.5))) infLoopDetector = true; + difference = _lower.sub(_upper).div(2).abs(); + if (_upper.gt("1e18")) break; + if (_upper.eq(previousUpper)) break; //Another infinite loop catcher + } + if (_upper.gt("1e18")) break; + if (!decreasingFound) break; //If there's no decreasing range, then even if an error caused lastValid to gain a value, the minimum can't exist + if (lastValid == FC(1, 10, 1)) { + //Whatever we're searching for, it doesn't exist. If there's no minimum, then there's no maximum either, so either way we can end the loop here. + break; + } + if (stage == 1) minimum = lastValid;else if (stage == 3) maximum = lastValid; + stage++; + } + //Now we have the minimum and maximum, so it's time to calculate the actual super-root. + //First, check if the root is in the increasing range. + _lower = minimum; + _upper = FC(1, 1, -18); + var _previous = _upper; + var _guess = Decimal.dZero; + var _loopGoing = true; + while (_loopGoing) { + 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; + } + //using guess.neq(minimum) led to imprecision errors, so here's a fixed version of that + if (!_guess.eq_tolerance(minimum, 1e-15)) { + return _guess.pow10().recip(); + } else { + //If guess == minimum, we haven't actually found the super-root, the algorithm just kept going down trying to find a super-root that's not in the increasing range. + //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; + } + _lower = FC(1, 10, 1); + _upper = maximum; + _previous = _upper; + _guess = Decimal.dZero; + _loopGoing = true; + while (_loopGoing) { + 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; + } + return _guess.pow10().recip(); + } + } + } + //Pentation/pentate: The result of tetrating 'height' times in a row. An absurdly strong operator - Decimal.pentate(2, 4.28) and Decimal.pentate(10, 2.37) are already too huge for break_eternity.js! + // https://en.wikipedia.org/wiki/Pentation }, { key: "pentate", value: function pentate() { 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); var oldheight = height; height = Math.trunc(height); - var fracheight = oldheight - height; //I have no idea if this is a meaningful approximation for pentation to continuous heights, but it is monotonic and continuous. - + var fracheight = oldheight - height; + //I have no idea if this is a meaningful approximation for pentation to continuous heights, but it is monotonic and continuous. if (fracheight !== 0) { if (payload.eq(Decimal.dOne)) { ++height; payload = Decimal.fromNumber(fracheight); } else { if (this.eq(10)) { - payload = payload.layeradd10(fracheight); + payload = payload.layeradd10(fracheight, linear); } else { - payload = payload.layeradd(fracheight, this); + payload = payload.layeradd(fracheight, this, linear); } } } - for (var i = 0; i < height; ++i) { - payload = this.tetrate(payload.toNumber()); //bail if we're NaN - + payload = this.tetrate(payload.toNumber(), Decimal.dOne, linear); + //bail if we're NaN if (!isFinite(payload.layer) || !isFinite(payload.mag)) { return payload.normalize(); - } //give up after 10 iterations if nothing is happening - - + } + //give up after 10 iterations if nothing is happening if (i > 10) { return payload; } } - return payload; - } // trig functions! - + } + // trig functions! }, { key: "sin", value: function sin() { if (this.mag < 0) { return this; } - if (this.layer === 0) { return Decimal.fromNumber(Math.sin(this.sign * this.mag)); } - return FC_NN(0, 0, 0); } }, { @@ -2400,11 +2480,9 @@ var Decimal = /*#__PURE__*/function () { if (this.mag < 0) { return Decimal.dOne; } - if (this.layer === 0) { return Decimal.fromNumber(Math.cos(this.sign * this.mag)); } - return FC_NN(0, 0, 0); } }, { @@ -2413,11 +2491,9 @@ var Decimal = /*#__PURE__*/function () { if (this.mag < 0) { return this; } - if (this.layer === 0) { return Decimal.fromNumber(Math.tan(this.sign * this.mag)); } - return FC_NN(0, 0, 0); } }, { @@ -2426,11 +2502,9 @@ var Decimal = /*#__PURE__*/function () { if (this.mag < 0) { return this; } - if (this.layer === 0) { return Decimal.fromNumber(Math.asin(this.sign * this.mag)); } - return FC_NN(Number.NaN, Number.NaN, Number.NaN); } }, { @@ -2439,11 +2513,9 @@ var Decimal = /*#__PURE__*/function () { if (this.mag < 0) { return Decimal.fromNumber(Math.acos(this.toNumber())); } - if (this.layer === 0) { return Decimal.fromNumber(Math.acos(this.sign * this.mag)); } - return FC_NN(Number.NaN, Number.NaN, Number.NaN); } }, { @@ -2452,11 +2524,9 @@ var Decimal = /*#__PURE__*/function () { if (this.mag < 0) { return this; } - if (this.layer === 0) { return Decimal.fromNumber(Math.atan(this.sign * this.mag)); } - return Decimal.fromNumber(Math.atan(this.sign * 1.8e308)); } }, { @@ -2490,26 +2560,22 @@ var Decimal = /*#__PURE__*/function () { if (this.abs().gte(1)) { return FC_NN(Number.NaN, Number.NaN, Number.NaN); } - return Decimal.ln(this.add(1).div(Decimal.fromNumber(1).sub(this))).div(2); } /** * Joke function from Realm Grinder */ - }, { key: "ascensionPenalty", value: function ascensionPenalty(ascensions) { if (ascensions === 0) { return this; } - return this.root(Decimal.pow(10, ascensions)); } /** * Joke function from Cookie Clicker. It's 'egg' */ - }, { key: "egg", value: function egg() { @@ -2584,7 +2650,6 @@ var Decimal = /*#__PURE__*/function () { * Use `new Decimal(value)` to explicitly create a writeable copy if mutation * is required. */ - }, { key: "fromValue_noAlloc", value: function fromValue_noAlloc(value) { @@ -2592,11 +2657,9 @@ var Decimal = /*#__PURE__*/function () { return value; } else if (typeof value === "string") { var cached = Decimal.fromStringCache.get(value); - if (cached !== undefined) { return cached; } - return Decimal.fromString(value); } else if (typeof value === "number") { return Decimal.fromNumber(value); @@ -2722,6 +2785,21 @@ var Decimal = /*#__PURE__*/function () { value: function reciprocate(value) { return D(value).reciprocate(); } + }, { + key: "mod", + value: function mod(value, other) { + return D(value).mod(other); + } + }, { + key: "modulo", + value: function modulo(value, other) { + return D(value).modulo(other); + } + }, { + key: "modular", + value: function modular(value, other) { + return D(value).modular(other); + } }, { key: "cmp", value: function cmp(value, other) { @@ -2743,11 +2821,9 @@ var Decimal = /*#__PURE__*/function () { function isNaN(_x) { return _isNaN.apply(this, arguments); } - isNaN.toString = function () { return _isNaN.toString(); }; - return isNaN; }(function (value) { value = D(value); @@ -2759,11 +2835,9 @@ var Decimal = /*#__PURE__*/function () { function isFinite(_x2) { return _isFinite.apply(this, arguments); } - isFinite.toString = function () { return _isFinite.toString(); }; - return isFinite; }(function (value) { value = D(value); @@ -2989,38 +3063,44 @@ var Decimal = /*#__PURE__*/function () { value: function tetrate(value) { var height = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2; var payload = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : FC_NN(1, 0, 1); - return D(value).tetrate(height, payload); + var linear = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; + return D(value).tetrate(height, payload, linear); } }, { key: "iteratedexp", value: function iteratedexp(value) { var height = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2; var payload = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : FC_NN(1, 0, 1); - return D(value).iteratedexp(height, payload); + var linear = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; + return D(value).iteratedexp(height, payload, linear); } }, { key: "iteratedlog", value: function iteratedlog(value) { var base = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 10; var times = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1; - return D(value).iteratedlog(base, times); + var linear = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; + return D(value).iteratedlog(base, times, linear); } }, { key: "layeradd10", value: function layeradd10(value, diff) { - return D(value).layeradd10(diff); + var linear = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + return D(value).layeradd10(diff, linear); } }, { key: "layeradd", value: function layeradd(value, diff) { var base = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 10; - return D(value).layeradd(diff, base); + var linear = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; + return D(value).layeradd(diff, base, linear); } }, { key: "slog", value: function slog(value) { var base = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 10; - return D(value).slog(base); + var linear = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + return D(value).slog(base, 100, linear); } }, { key: "lambertw", @@ -3032,12 +3112,18 @@ var Decimal = /*#__PURE__*/function () { value: function ssqrt(value) { return D(value).ssqrt(); } + }, { + key: "linear_sroot", + value: function linear_sroot(value, height) { + return D(value).linear_sroot(height); + } }, { key: "pentate", value: function pentate(value) { var height = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2; var payload = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : FC_NN(1, 0, 1); - return D(value).pentate(height, payload); + var linear = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; + return D(value).pentate(height, payload, linear); } /** * If you're willing to spend 'resourcesAvailable' and want to buy something @@ -3045,7 +3131,6 @@ var Decimal = /*#__PURE__*/function () { * multiply by priceRatio, already own currentOwned), how much of it can you buy? * Adapted from Trimps source code. */ - }, { key: "affordGeometricSeries", value: function affordGeometricSeries(resourcesAvailable, priceStart, priceRatio, currentOwned) { @@ -3055,7 +3140,6 @@ var Decimal = /*#__PURE__*/function () { * How much resource would it cost to buy (numItems) items if you already have currentOwned, * the initial price is priceStart and it multiplies by priceRatio each purchase? */ - }, { key: "sumGeometricSeries", value: function sumGeometricSeries(numItems, priceStart, priceRatio, currentOwned) { @@ -3066,7 +3150,6 @@ var Decimal = /*#__PURE__*/function () { * increasing cost each purchase (start at priceStart, add by priceAdd, already own currentOwned), * how much of it can you buy? */ - }, { key: "affordArithmeticSeries", value: function affordArithmeticSeries(resourcesAvailable, priceStart, priceAdd, currentOwned) { @@ -3077,7 +3160,6 @@ var Decimal = /*#__PURE__*/function () { * the initial price is priceStart and it adds priceAdd each purchase? * Adapted from http://www.mathwords.com/a/arithmetic_series.htm */ - }, { key: "sumArithmeticSeries", value: function sumArithmeticSeries(numItems, priceStart, priceAdd, currentOwned) { @@ -3089,7 +3171,6 @@ var Decimal = /*#__PURE__*/function () { * From Frozen Cookies: * http://cookieclicker.wikia.com/wiki/Frozen_Cookies_(JavaScript_Add-on)#Efficiency.3F_What.27s_that.3F */ - }, { key: "efficiencyOfPurchase", value: function efficiencyOfPurchase(cost, currentRpS, deltaRpS) { @@ -3103,27 +3184,23 @@ var Decimal = /*#__PURE__*/function () { if (Math.random() * 20 < 1) { return FC_NN(0, 0, 0); } - - var randomsign = Math.random() > 0.5 ? 1 : -1; //5% of the time, return 1 or -1 - + var randomsign = Math.random() > 0.5 ? 1 : -1; + //5% of the time, return 1 or -1 if (Math.random() * 20 < 1) { return FC_NN(randomsign, 0, 1); - } //pick a random layer - - + } + //pick a random layer var layer = Math.floor(Math.random() * (maxLayers + 1)); - var randomexp = layer === 0 ? Math.random() * 616 - 308 : Math.random() * 16; //10% of the time, make it a simple power of 10 - + var randomexp = layer === 0 ? Math.random() * 616 - 308 : Math.random() * 16; + //10% of the time, make it a simple power of 10 if (Math.random() > 0.9) { randomexp = Math.trunc(randomexp); } - - var randommag = Math.pow(10, randomexp); //10% of the time, trunc mag - + var randommag = Math.pow(10, randomexp); + //10% of the time, trunc mag if (Math.random() > 0.9) { randommag = Math.trunc(randommag); } - return FC(randomsign, layer, randommag); } }, { @@ -3152,7 +3229,6 @@ var Decimal = /*#__PURE__*/function () { key: "sumArithmeticSeries_core", value: function sumArithmeticSeries_core(numItems, priceStart, priceAdd, currentOwned) { var actualStart = priceStart.add(currentOwned.mul(priceAdd)); // (n/2)*(2*a+(n-1)*d) - return numItems.div(2).mul(actualStart.mul(2).plus(numItems.sub(1).mul(priceAdd))); } }, { @@ -3167,7 +3243,6 @@ var Decimal = /*#__PURE__*/function () { if (base > 10) { return height - 1; } - return Decimal.critical_section(base, height, critical_slog_values); } }, { @@ -3180,30 +3255,25 @@ var Decimal = /*#__PURE__*/function () { value: function critical_section(base, height, grid) { //this part is simple at least, since it's just 0.1 to 0.9 height *= 10; - if (height < 0) { height = 0; } - if (height > 10) { height = 10; - } //have to do this complicated song and dance since one of the critical_headers is Math.E, and in the future I'd like 1.5 as well - - + } + //have to do this complicated song and dance since one of the critical_headers is Math.E, and in the future I'd like 1.5 as well if (base < 2) { base = 2; } - if (base > 10) { base = 10; } - var lower = 0; - var upper = 0; //basically, if we're between bases, we interpolate each bases' relevant values together + var upper = 0; + //basically, if we're between bases, we interpolate each bases' relevant values together //then we interpolate based on what the fractional height is. //accuracy could be improved by doing a non-linear interpolation (maybe), by adding more bases and heights (definitely) but this is AFAIK the best you can get without running some pari.gp or mathematica program to calculate exact values //however, do note http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html can do it for arbitrary heights but not for arbitrary bases (2, e, 10 present) - for (var i = 0; i < critical_headers.length; ++i) { if (critical_headers[i] == base) { // exact match @@ -3218,11 +3288,10 @@ var Decimal = /*#__PURE__*/function () { break; } } - - var frac = height - Math.floor(height); //improvement - you get more accuracy (especially around 0.9-1.0) by doing log, then frac, then powing the result + var frac = height - Math.floor(height); + //improvement - you get more accuracy (especially around 0.9-1.0) by doing log, then frac, then powing the result //(we could pre-log the lookup table, but then fractional bases would get Weird) //also, use old linear for slog (values 0 or less in critical section). maybe something else is better but haven't thought about what yet - if (lower <= 0 || upper <= 0) { return lower * (1 - frac) + upper * frac; } else { @@ -3230,7 +3299,6 @@ var Decimal = /*#__PURE__*/function () { } } }]); - return Decimal; }(); Decimal.dZero = FC_NN(0, 0, 0); @@ -3243,16 +3311,16 @@ Decimal.dInf = FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); Decimal.dNegInf = FC_NN(-1, Number.NEGATIVE_INFINITY, Number.NEGATIVE_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); // return Decimal; +Decimal.fromStringCache = new LRUCache(DEFAULT_FROM_STRING_CACHE_SIZE); +// return Decimal; // Optimise Decimal aliases. // We can't do this optimisation before Decimal is assigned. - D = Decimal.fromValue_noAlloc; FC = Decimal.fromComponents; -FC_NN = Decimal.fromComponents_noNormalize; // eslint-disable-next-line @typescript-eslint/no-unused-vars - -Decimal.fromMantissaExponent; // eslint-disable-next-line @typescript-eslint/no-unused-vars - +FC_NN = Decimal.fromComponents_noNormalize; +// eslint-disable-next-line @typescript-eslint/no-unused-vars +Decimal.fromMantissaExponent; +// eslint-disable-next-line @typescript-eslint/no-unused-vars Decimal.fromMantissaExponent_noNormalize; export { Decimal as default }; diff --git a/break_eternity.js b/break_eternity.js index e15caff..da8400e 100644 --- a/break_eternity.js +++ b/break_eternity.js @@ -9,17 +9,15 @@ throw new TypeError("Cannot call a class as a function"); } } - function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, descriptor.key, descriptor); + Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } - function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); @@ -28,6 +26,20 @@ }); return Constructor; } + function _toPrimitive(input, hint) { + if (typeof input !== "object" || input === null) return input; + var prim = input[Symbol.toPrimitive]; + if (prim !== undefined) { + var res = prim.call(input, hint || "default"); + if (typeof res !== "object") return res; + throw new TypeError("@@toPrimitive must return a primitive value."); + } + return (hint === "string" ? String : Number)(input); + } + function _toPropertyKey(arg) { + var key = _toPrimitive(arg, "string"); + return typeof key === "symbol" ? key : String(key); + } /** * A LRU cache intended for caching pure functions. @@ -43,18 +55,16 @@ */ function LRUCache(maxSize) { _classCallCheck(this, LRUCache); - - this.map = new Map(); // Invariant: Exactly one of the below is true before and after calling a + this.map = new Map(); + // Invariant: Exactly one of the below is true before and after calling a // LRUCache method: // - first and last are both undefined, and map.size() is 0. // - first and last are the same object, and map.size() is 1. // - first and last are different objects, and map.size() is greater than 1. - this.first = undefined; this.last = undefined; this.maxSize = maxSize; } - _createClass(LRUCache, [{ key: "size", get: function get() { @@ -66,53 +76,48 @@ * @param key The key to get. * @returns The cached value, or undefined if key is not in the cache. */ - }, { key: "get", value: function get(key) { var node = this.map.get(key); - if (node === undefined) { return undefined; - } // It is guaranteed that there is at least one item in the cache. + } + // It is guaranteed that there is at least one item in the cache. // Therefore, first and last are guaranteed to be a ListNode... // but if there is only one item, they might be the same. // Update the order of the list to make this node the first node in the // list. // This isn't needed if this node is already the first node in the list. - - if (node !== this.first) { // As this node is DIFFERENT from the first node, it is guaranteed that // there are at least two items in the cache. // However, this node could possibly be the last item. if (node === this.last) { // This node IS the last node. - this.last = node.prev; // From the invariants, there must be at least two items in the cache, + this.last = node.prev; + // From the invariants, there must be at least two items in the cache, // so node - which is the original "last node" - must have a defined // previous node. Therefore, this.last - set above - must be defined // here. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.last.next = undefined; } else { // This node is somewhere in the middle of the list, so there must be at // least THREE items in the list, and this node's prev and next must be // defined here. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - node.prev.next = node.next; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - + node.prev.next = node.next; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion node.next.prev = node.prev; } - - node.next = this.first; // From the invariants, there must be at least two items in the cache, so + node.next = this.first; + // From the invariants, there must be at least two items in the cache, so // this.first must be a valid ListNode. // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.first.prev = node; this.first = node; } - return node.value; } /** @@ -122,7 +127,6 @@ * @param value The value of the entry. * @throws Error, if the map already contains the key. */ - }, { key: "set", value: function set(key, value) { @@ -130,13 +134,11 @@ if (this.maxSize < 1) { return; } - if (this.map.has(key)) { throw new Error("Cannot update existing keys in the cache"); } - - var node = new ListNode(key, value); // Move node to the front of the list. - + var node = new ListNode(key, value); + // Move node to the front of the list. if (this.first === undefined) { // If the first is undefined, the last is undefined too. // Therefore, this cache has no items in it. @@ -148,9 +150,7 @@ this.first.prev = node; this.first = node; } - this.map.set(key, node); - while (this.map.size > this.maxSize) { // We are guaranteed that this.maxSize >= 1, // so this.map.size is guaranteed to be >= 2, @@ -159,22 +159,19 @@ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion var last = this.last; this.map["delete"](last.key); - this.last = last.prev; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - + this.last = last.prev; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion this.last.next = undefined; } } }]); - return LRUCache; }(); /** * A node in a doubly linked list. */ - var ListNode = /*#__PURE__*/_createClass(function ListNode(key, value) { _classCallCheck(this, ListNode); - this.next = undefined; this.prev = undefined; this.key = key; @@ -182,112 +179,110 @@ }); var MAX_SIGNIFICANT_DIGITS = 17; //Maximum number of digits of precision to assume in Number - var EXP_LIMIT = 9e15; //If we're ABOVE this value, increase a layer. (9e15 is close to the largest integer that can fit in a Number.) - var LAYER_DOWN = Math.log10(9e15); var FIRST_NEG_LAYER = 1 / 9e15; //At layer 0, smaller non-zero numbers than this become layer 1 numbers with negative mag. After that the pattern continues as normal. - var NUMBER_EXP_MAX = 308; //The largest exponent that can appear in a Number, though not all mantissas are valid here. - var NUMBER_EXP_MIN = -324; //The smallest exponent that can appear in a Number, though not all mantissas are valid here. - var MAX_ES_IN_A_ROW = 5; //For default toString behaviour, when to swap from eee... to (e^n) syntax. - var DEFAULT_FROM_STRING_CACHE_SIZE = (1 << 10) - 1; // The default size of the LRU cache used to cache Decimal.fromString. - var powerOf10 = function () { // We need this lookup table because Math.pow(10, exponent) // when exponent's absolute value is large is slightly inaccurate. // You can fix it with the power of math... or just make a lookup table. // Faster AND simpler var powersOf10 = []; - for (var i = NUMBER_EXP_MIN + 1; i <= NUMBER_EXP_MAX; i++) { powersOf10.push(Number("1e" + i)); } - var indexOf0InPowersOf10 = 323; return function (power) { return powersOf10[power + indexOf0InPowersOf10]; }; - }(); //tetration/slog to real height stuff + }(); + //tetration/slog to real height stuff //background info and tables of values for critical functions taken here: https://github.com/Patashu/break_eternity.js/issues/22 - - var critical_headers = [2, Math.E, 3, 4, 5, 6, 7, 8, 9, 10]; - var critical_tetr_values = [[// Base 2 (using http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html ) - 1, 1.0891180521811202527, 1.1789767925673958433, 1.2701455431742086633, 1.3632090180450091941, 1.4587818160364217007, 1.5575237916251418333, 1.6601571006859253673, 1.7674858188369780435, 1.8804192098842727359, 2], [// Base E (using http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html ) + var critical_tetr_values = [[ + // Base 2 (using http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html ) + 1, 1.0891180521811202527, 1.1789767925673958433, 1.2701455431742086633, 1.3632090180450091941, 1.4587818160364217007, 1.5575237916251418333, 1.6601571006859253673, 1.7674858188369780435, 1.8804192098842727359, 2], [ + // Base E (using http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html ) 1, 1.1121114330934078681, 1.2310389249316089299, 1.3583836963111376089, 1.4960519303993531879, 1.6463542337511945810, 1.8121385357018724464, 1.9969713246183068478, 2.2053895545527544330, 2.4432574483385252544, Math.E //1.0 - ], [// Base 3 - 1, 1.1187738849693603, 1.2464963939368214, 1.38527004705667, 1.5376664685821402, 1.7068895236551784, 1.897001227148399, 2.1132403089001035, 2.362480153784171, 2.6539010333870774, 3], [// Base 4 - 1, 1.1367350847096405, 1.2889510672956703, 1.4606478703324786, 1.6570295196661111, 1.8850062585672889, 2.1539465047453485, 2.476829779693097, 2.872061932789197, 3.3664204535587183, 4], [// Base 5 - 1, 1.1494592900767588, 1.319708228183931, 1.5166291280087583, 1.748171114438024, 2.0253263297298045, 2.3636668498288547, 2.7858359149579424, 3.3257226212448145, 4.035730287722532, 5], [// Base 6 - 1, 1.159225940787673, 1.343712473580932, 1.5611293155111927, 1.8221199554561318, 2.14183924486326, 2.542468319282638, 3.0574682501653316, 3.7390572020926873, 4.6719550537360774, 6], [// Base 7 - 1, 1.1670905356972596, 1.3632807444991446, 1.5979222279405536, 1.8842640123816674, 2.2416069644878687, 2.69893426559423, 3.3012632110403577, 4.121250340630164, 5.281493033448316, 7], [// Base 8 - 1, 1.1736630594087796, 1.379783782386201, 1.6292821855668218, 1.9378971836180754, 2.3289975651071977, 2.8384347394720835, 3.5232708454565906, 4.478242031114584, 5.868592169644505, 8], [// Base 9 - 1, 1.1793017514670474, 1.394054150657457, 1.65664127441059, 1.985170999970283, 2.4069682290577457, 2.9647310119960752, 3.7278665320924946, 4.814462547283592, 6.436522247411611, 9], [// Base 10 (using http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html ) + ], [ + // Base 3 + 1, 1.1187738849693603, 1.2464963939368214, 1.38527004705667, 1.5376664685821402, 1.7068895236551784, 1.897001227148399, 2.1132403089001035, 2.362480153784171, 2.6539010333870774, 3], [ + // Base 4 + 1, 1.1367350847096405, 1.2889510672956703, 1.4606478703324786, 1.6570295196661111, 1.8850062585672889, 2.1539465047453485, 2.476829779693097, 2.872061932789197, 3.3664204535587183, 4], [ + // Base 5 + 1, 1.1494592900767588, 1.319708228183931, 1.5166291280087583, 1.748171114438024, 2.0253263297298045, 2.3636668498288547, 2.7858359149579424, 3.3257226212448145, 4.035730287722532, 5], [ + // Base 6 + 1, 1.159225940787673, 1.343712473580932, 1.5611293155111927, 1.8221199554561318, 2.14183924486326, 2.542468319282638, 3.0574682501653316, 3.7390572020926873, 4.6719550537360774, 6], [ + // Base 7 + 1, 1.1670905356972596, 1.3632807444991446, 1.5979222279405536, 1.8842640123816674, 2.2416069644878687, 2.69893426559423, 3.3012632110403577, 4.121250340630164, 5.281493033448316, 7], [ + // Base 8 + 1, 1.1736630594087796, 1.379783782386201, 1.6292821855668218, 1.9378971836180754, 2.3289975651071977, 2.8384347394720835, 3.5232708454565906, 4.478242031114584, 5.868592169644505, 8], [ + // Base 9 + 1, 1.1793017514670474, 1.394054150657457, 1.65664127441059, 1.985170999970283, 2.4069682290577457, 2.9647310119960752, 3.7278665320924946, 4.814462547283592, 6.436522247411611, 9], [ + // Base 10 (using http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html ) 1, 1.1840100246247336579, 1.4061375836156954169, 1.6802272208863963918, 2.026757028388618927, 2.4770056063449647580, 3.0805252717554819987, 3.9191964192627283911, 5.1351528408331864230, 6.9899611795347148455, 10]]; - var critical_slog_values = [[// Base 2 - -1, -0.9194161097107025, -0.8335625019330468, -0.7425599821143978, -0.6466611521029437, -0.5462617907227869, -0.4419033816638769, -0.3342645487554494, -0.224140440909962, -0.11241087890006762, 0], [// Base E + var critical_slog_values = [[ + // Base 2 + -1, -0.9194161097107025, -0.8335625019330468, -0.7425599821143978, -0.6466611521029437, -0.5462617907227869, -0.4419033816638769, -0.3342645487554494, -0.224140440909962, -0.11241087890006762, 0], [ + // Base E -1, -0.90603157029014, -0.80786507256596, -0.7064666939634, -0.60294836853664, -0.49849837513117, -0.39430303318768, -0.29147201034755, -0.19097820800866, -0.09361896280296, 0 //1.0 - ], [// Base 3 - -1, -0.9021579584316141, -0.8005762598234203, -0.6964780623319391, -0.5911906810998454, -0.486050182576545, -0.3823089430815083, -0.28106046722897615, -0.1831906535795894, -0.08935809204418144, 0], [// Base 4 - -1, -0.8917227442365535, -0.781258746326964, -0.6705130326902455, -0.5612813129406509, -0.4551067709033134, -0.35319256652135966, -0.2563741554088552, -0.1651412821106526, -0.0796919581982668, 0], [// Base 5 - -1, -0.8843387974366064, -0.7678744063886243, -0.6529563724510552, -0.5415870994657841, -0.4352842206588936, -0.33504449124791424, -0.24138853420685147, -0.15445285440944467, -0.07409659641336663, 0], [// Base 6 - -1, -0.8786709358426346, -0.7577735191184886, -0.6399546189952064, -0.527284921869926, -0.4211627631006314, -0.3223479611761232, -0.23107655627789858, -0.1472057700818259, -0.07035171210706326, 0], [// Base 7 - -1, -0.8740862815291583, -0.7497032990976209, -0.6297119746181752, -0.5161838335958787, -0.41036238255751956, -0.31277212146489963, -0.2233976621705518, -0.1418697367979619, -0.06762117662323441, 0], [// Base 8 - -1, -0.8702632331800649, -0.7430366914122081, -0.6213373075161548, -0.5072025698095242, -0.40171437727184167, -0.30517930701410456, -0.21736343968190863, -0.137710238299109, -0.06550774483471955, 0], [// Base 9 - -1, -0.8670016295947213, -0.7373984232432306, -0.6143173985094293, -0.49973884395492807, -0.394584953527678, -0.2989649949848695, -0.21245647317021688, -0.13434688362382652, -0.0638072667348083, 0], [// Base 10 + ], [ + // Base 3 + -1, -0.9021579584316141, -0.8005762598234203, -0.6964780623319391, -0.5911906810998454, -0.486050182576545, -0.3823089430815083, -0.28106046722897615, -0.1831906535795894, -0.08935809204418144, 0], [ + // Base 4 + -1, -0.8917227442365535, -0.781258746326964, -0.6705130326902455, -0.5612813129406509, -0.4551067709033134, -0.35319256652135966, -0.2563741554088552, -0.1651412821106526, -0.0796919581982668, 0], [ + // Base 5 + -1, -0.8843387974366064, -0.7678744063886243, -0.6529563724510552, -0.5415870994657841, -0.4352842206588936, -0.33504449124791424, -0.24138853420685147, -0.15445285440944467, -0.07409659641336663, 0], [ + // Base 6 + -1, -0.8786709358426346, -0.7577735191184886, -0.6399546189952064, -0.527284921869926, -0.4211627631006314, -0.3223479611761232, -0.23107655627789858, -0.1472057700818259, -0.07035171210706326, 0], [ + // Base 7 + -1, -0.8740862815291583, -0.7497032990976209, -0.6297119746181752, -0.5161838335958787, -0.41036238255751956, -0.31277212146489963, -0.2233976621705518, -0.1418697367979619, -0.06762117662323441, 0], [ + // Base 8 + -1, -0.8702632331800649, -0.7430366914122081, -0.6213373075161548, -0.5072025698095242, -0.40171437727184167, -0.30517930701410456, -0.21736343968190863, -0.137710238299109, -0.06550774483471955, 0], [ + // Base 9 + -1, -0.8670016295947213, -0.7373984232432306, -0.6143173985094293, -0.49973884395492807, -0.394584953527678, -0.2989649949848695, -0.21245647317021688, -0.13434688362382652, -0.0638072667348083, 0], [ + // Base 10 -1, -0.8641642839543857, -0.732534623168535, -0.6083127477059322, -0.4934049257184696, -0.3885773075899922, -0.29376029055315767, -0.2083678561173622, -0.13155653399373268, -0.062401588652553186, 0]]; - var D = function D(value) { return Decimal.fromValue_noAlloc(value); }; - var FC = function FC(sign, layer, mag) { return Decimal.fromComponents(sign, layer, mag); }; - var FC_NN = function FC_NN(sign, layer, mag) { return Decimal.fromComponents_noNormalize(sign, layer, mag); - }; // eslint-disable-next-line @typescript-eslint/no-unused-vars - + }; var decimalPlaces = function decimalPlaces(value, places) { var len = places + 1; var numDigits = Math.ceil(Math.log10(Math.abs(value))); var rounded = Math.round(value * Math.pow(10, len - numDigits)) * Math.pow(10, numDigits - len); return parseFloat(rounded.toFixed(Math.max(len - numDigits, 0))); }; - var f_maglog10 = function f_maglog10(n) { return Math.sign(n) * Math.log10(Math.abs(n)); - }; //from HyperCalc source code - - + }; + //from HyperCalc source code var f_gamma = function f_gamma(n) { if (!isFinite(n)) { return n; } - if (n < -50) { if (n === Math.trunc(n)) { return Number.NEGATIVE_INFINITY; } - return 0; } - var scal1 = 1; - while (n < 10) { scal1 = scal1 * n; ++n; } - n -= 1; var l = 0.9189385332046727; //0.5*Math.log(2*Math.PI) - l = l + (n + 0.5) * Math.log(n); l = l - n; var n2 = n * n; @@ -309,99 +304,82 @@ 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 - var f_lambertw = function f_lambertw(z) { var tol = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1e-10; 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; } 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); - if (Math.abs(wn - w) < tol * Math.abs(wn)) { return wn; } else { w = wn; } } - - throw Error("Iteration failed to converge: ".concat(z.toString())); //return Number.NaN; - }; //from https://github.com/scipy/scipy/blob/8dba340293fe20e62e173bdf2c10ae208286692f/scipy/special/lambertw.pxd + throw Error("Iteration failed to converge: ".concat(z.toString())); + //return Number.NaN; + }; + //from https://github.com/scipy/scipy/blob/8dba340293fe20e62e173bdf2c10ae208286692f/scipy/special/lambertw.pxd // 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) { var tol = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1e-10; var w; var ew, wewz, wn; - if (!Number.isFinite(z.mag)) { return z; } - if (z.eq(Decimal.dZero)) { return z; } - 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); //Halley's method; see 5.9 in [1] - + } + //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(); wewz = w.sub(z.mul(ew)); wn = w.sub(wewz.div(w.add(1).sub(w.add(2).mul(wewz).div(Decimal.mul(2, w).add(2))))); - if (Decimal.abs(wn.sub(w)).lt(Decimal.abs(wn).mul(tol))) { return wn; } else { w = wn; } } - - throw Error("Iteration failed to converge: ".concat(z.toString())); //return Decimal.dNaN; + throw Error("Iteration failed to converge: ".concat(z.toString())); + //return Decimal.dNaN; } /** - * The Decimal's value is simply mantissa * 10^exponent. + * The value of the Decimal is sign * 10^10^10...^mag, with (layer) 10s. If the layer is not 0, then negative mag means it's the reciprocal of the corresponding number with positive mag. */ - - var Decimal = /*#__PURE__*/function () { function Decimal(value) { _classCallCheck(this, Decimal); - this.sign = 0; this.mag = 0; this.layer = 0; - if (value instanceof Decimal) { this.fromDecimal(value); } else if (typeof value === "number") { @@ -410,23 +388,20 @@ this.fromString(value); } } - _createClass(Decimal, [{ key: "m", get: function get() { if (this.sign === 0) { return 0; } else if (this.layer === 0) { - var exp = Math.floor(Math.log10(this.mag)); //handle special case 5e-324 - + var exp = Math.floor(Math.log10(this.mag)); + //handle special case 5e-324 var man; - if (this.mag === 5e-324) { man = 5; } else { man = this.mag / powerOf10(exp); } - return this.sign * man; } else if (this.layer === 1) { var residue = this.mag - Math.floor(this.mag); @@ -442,7 +417,6 @@ } else { //don't even pretend mantissa is meaningful this.sign = Math.sign(value); - if (this.sign === 0) { this.layer = 0; this.exponent = 0; @@ -480,8 +454,8 @@ } else { this.sign = value; } - } // Object.defineProperty(Decimal.prototype, "mantissa", { - + } + // Object.defineProperty(Decimal.prototype, "mantissa", { }, { key: "mantissa", get: function get() { @@ -520,23 +494,19 @@ this.layer = 0; return this; } - if (this.layer === 0 && this.mag < 0) { //extract sign from negative mag at layer 0 this.mag = -this.mag; this.sign = -this.sign; - } //Handle shifting from layer 0 to negative layers. - - + } + //Handle shifting from layer 0 to negative layers. if (this.layer === 0 && this.mag < FIRST_NEG_LAYER) { this.layer += 1; this.mag = Math.log10(this.mag); return this; } - var absmag = Math.abs(this.mag); var signmag = Math.sign(this.mag); - if (absmag >= EXP_LIMIT) { this.layer += 1; this.mag = signmag * Math.log10(absmag); @@ -544,7 +514,6 @@ } else { while (absmag < LAYER_DOWN && this.layer > 0) { this.layer -= 1; - if (this.layer === 0) { this.mag = Math.pow(10, this.mag); } else { @@ -553,7 +522,6 @@ signmag = Math.sign(this.mag); } } - if (this.layer === 0) { if (this.mag < 0) { //extract sign from negative mag at layer 0 @@ -565,7 +533,6 @@ } } } - return this; } }, { @@ -624,215 +591,181 @@ value: function fromString(value) { var originalValue = value; var cached = Decimal.fromStringCache.get(originalValue); - if (cached !== undefined) { return this.fromDecimal(cached); } - { value = value.replace(",", ""); - } //Handle x^^^y format. - - + } + //Handle x^^^y format. var pentationparts = value.split("^^^"); - if (pentationparts.length === 2) { var _base = parseFloat(pentationparts[0]); - var _height = parseFloat(pentationparts[1]); - var heightparts = pentationparts[1].split(";"); var payload = 1; - if (heightparts.length === 2) { payload = parseFloat(heightparts[1]); - if (!isFinite(payload)) { payload = 1; } } - if (isFinite(_base) && isFinite(_height)) { var result = Decimal.pentate(_base, _height, payload); this.sign = result.sign; this.layer = result.layer; this.mag = result.mag; - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } - } //Handle x^^y format. - - + } + //Handle x^^y format. var tetrationparts = value.split("^^"); - if (tetrationparts.length === 2) { var _base2 = parseFloat(tetrationparts[0]); - var _height2 = parseFloat(tetrationparts[1]); - var _heightparts = tetrationparts[1].split(";"); - var _payload = 1; - if (_heightparts.length === 2) { _payload = parseFloat(_heightparts[1]); - if (!isFinite(_payload)) { _payload = 1; } } - if (isFinite(_base2) && isFinite(_height2)) { var _result = Decimal.tetrate(_base2, _height2, _payload); - this.sign = _result.sign; this.layer = _result.layer; this.mag = _result.mag; - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } - } //Handle x^y format. - - + } + //Handle x^y format. var powparts = value.split("^"); - if (powparts.length === 2) { var _base3 = parseFloat(powparts[0]); - var _exponent = parseFloat(powparts[1]); - if (isFinite(_base3) && isFinite(_exponent)) { var _result2 = Decimal.pow(_base3, _exponent); - this.sign = _result2.sign; this.layer = _result2.layer; this.mag = _result2.mag; - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } - } //Handle various cases involving it being a Big Number. - - - value = value.trim().toLowerCase(); //handle X PT Y format. - + } + //Handle various cases involving it being a Big Number. + value = value.trim().toLowerCase(); + //handle X PT Y format. var base; var height; var ptparts = value.split("pt"); - if (ptparts.length === 2) { base = 10; height = parseFloat(ptparts[0]); ptparts[1] = ptparts[1].replace("(", ""); ptparts[1] = ptparts[1].replace(")", ""); - var _payload2 = parseFloat(ptparts[1]); - if (!isFinite(_payload2)) { _payload2 = 1; } - if (isFinite(base) && isFinite(height)) { var _result3 = Decimal.tetrate(base, height, _payload2); - this.sign = _result3.sign; this.layer = _result3.layer; this.mag = _result3.mag; - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } - } //handle XpY format (it's the same thing just with p). - - + } + //handle XpY format (it's the same thing just with p). ptparts = value.split("p"); - if (ptparts.length === 2) { base = 10; height = parseFloat(ptparts[0]); ptparts[1] = ptparts[1].replace("(", ""); ptparts[1] = ptparts[1].replace(")", ""); - var _payload3 = parseFloat(ptparts[1]); - if (!isFinite(_payload3)) { _payload3 = 1; } - if (isFinite(base) && isFinite(height)) { var _result4 = Decimal.tetrate(base, height, _payload3); - this.sign = _result4.sign; this.layer = _result4.layer; this.mag = _result4.mag; - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } } - + //handle XFY format + ptparts = value.split("f"); + if (ptparts.length === 2) { + base = 10; + ptparts[0] = ptparts[0].replace("(", ""); + ptparts[0] = ptparts[0].replace(")", ""); + var _payload4 = parseFloat(ptparts[0]); + ptparts[1] = ptparts[1].replace("(", ""); + ptparts[1] = ptparts[1].replace(")", ""); + height = parseFloat(ptparts[1]); + if (!isFinite(_payload4)) { + _payload4 = 1; + } + if (isFinite(base) && isFinite(height)) { + var _result5 = Decimal.tetrate(base, height, _payload4); + this.sign = _result5.sign; + this.layer = _result5.layer; + this.mag = _result5.mag; + if (Decimal.fromStringCache.maxSize >= 1) { + Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); + } + return this; + } + } var parts = value.split("e"); - var ecount = parts.length - 1; //Handle numbers that are exactly floats (0 or 1 es). - + var ecount = parts.length - 1; + //Handle numbers that are exactly floats (0 or 1 es). if (ecount === 0) { var numberAttempt = parseFloat(value); - if (isFinite(numberAttempt)) { this.fromNumber(numberAttempt); - if (Decimal.fromStringCache.size >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } } else if (ecount === 1) { //Very small numbers ("2e-3000" and so on) may look like valid floats but round to 0. var _numberAttempt = parseFloat(value); - if (isFinite(_numberAttempt) && _numberAttempt !== 0) { this.fromNumber(_numberAttempt); - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } - } //Handle new (e^N)X format. - - + } + //Handle new (e^N)X format. var newparts = value.split("e^"); - if (newparts.length === 2) { this.sign = 1; - if (newparts[0].charAt(0) == "-") { this.sign = -1; } - var layerstring = ""; - for (var i = 0; i < newparts[1].length; ++i) { var chrcode = newparts[1].charCodeAt(i); - if (chrcode >= 43 && chrcode <= 57 || chrcode === 101) { //is "0" to "9" or "+" or "-" or "." or "e" (or "," or "/") layerstring += newparts[1].charAt(i); @@ -841,93 +774,76 @@ this.layer = parseFloat(layerstring); this.mag = parseFloat(newparts[1].substr(i + 1)); this.normalize(); - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } } } - if (ecount < 1) { this.sign = 0; this.layer = 0; this.mag = 0; - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } - var mantissa = parseFloat(parts[0]); - if (mantissa === 0) { this.sign = 0; this.layer = 0; this.mag = 0; - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } - - var exponent = parseFloat(parts[parts.length - 1]); //handle numbers like AeBeC and AeeeeBeC - + var exponent = parseFloat(parts[parts.length - 1]); + //handle numbers like AeBeC and AeeeeBeC if (ecount >= 2) { var me = parseFloat(parts[parts.length - 2]); - if (isFinite(me)) { exponent *= Math.sign(me); exponent += f_maglog10(me); } - } //Handle numbers written like eee... (N es) X - - + } + //Handle numbers written like eee... (N es) X if (!isFinite(mantissa)) { this.sign = parts[0] === "-" ? -1 : 1; this.layer = ecount; this.mag = exponent; - } //Handle numbers written like XeY + } + //Handle numbers written like XeY else if (ecount === 1) { this.sign = Math.sign(mantissa); - this.layer = 1; //Example: 2e10 is equal to 10^log10(2e10) which is equal to 10^(10+log10(2)) - + this.layer = 1; + //Example: 2e10 is equal to 10^log10(2e10) which is equal to 10^(10+log10(2)) this.mag = exponent + Math.log10(Math.abs(mantissa)); - } //Handle numbers written like Xeee... (N es) Y + } + //Handle numbers written like Xeee... (N es) Y else { this.sign = Math.sign(mantissa); this.layer = ecount; - if (ecount === 2) { - var _result5 = Decimal.mul(FC(1, 2, exponent), D(mantissa)); - - this.sign = _result5.sign; - this.layer = _result5.layer; - this.mag = _result5.mag; - + var _result6 = Decimal.mul(FC(1, 2, exponent), D(mantissa)); + this.sign = _result6.sign; + this.layer = _result6.layer; + this.mag = _result6.mag; if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } else { //at eee and above, mantissa is too small to be recognizable! this.mag = exponent; } } - this.normalize(); - if (Decimal.fromStringCache.maxSize >= 1) { Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); } - return this; } }, { @@ -936,15 +852,12 @@ if (value instanceof Decimal) { return this.fromDecimal(value); } - if (typeof value === "number") { return this.fromNumber(value); } - if (typeof value === "string") { return this.fromString(value); } - this.sign = 0; this.layer = 0; this.mag = 0; @@ -956,7 +869,6 @@ if (!Number.isFinite(this.layer)) { return Number.NaN; } - if (this.layer === 0) { return this.sign * this.mag; } else if (this.layer === 1) { @@ -973,11 +885,9 @@ if (isNaN(this.m)) { return Number.NaN; } - if (this.m === 0) { return 0; } - return decimalPlaces(this.m, places); } }, { @@ -987,11 +897,9 @@ if (isNaN(this.mag)) { return Number.NaN; } - if (this.mag === 0) { return 0; } - return decimalPlaces(this.mag, places); } }, { @@ -1000,16 +908,13 @@ if (isNaN(this.layer) || isNaN(this.sign) || isNaN(this.mag)) { return "NaN"; } - if (this.mag === Number.POSITIVE_INFINITY || this.layer === Number.POSITIVE_INFINITY) { return this.sign === 1 ? "Infinity" : "-Infinity"; } - if (this.layer === 0) { if (this.mag < 1e21 && this.mag > 1e-7 || this.mag === 0) { return (this.sign * this.mag).toString(); } - return this.m + "e" + this.e; } else if (this.layer === 1) { return this.m + "e" + this.e; @@ -1028,7 +933,6 @@ if (this.layer === 0) { return (this.sign * this.mag).toExponential(places); } - return this.toStringWithDecimalPlaces(places); } }, { @@ -1037,7 +941,6 @@ if (this.layer === 0) { return (this.sign * this.mag).toFixed(places); } - return this.toStringWithDecimalPlaces(places); } }, { @@ -1046,11 +949,9 @@ if (this.e <= -7) { return this.toExponential(places - 1); } - if (places > this.e) { return this.toFixed(places - this.exponent - 1); } - return this.toExponential(places - 1); } }, { @@ -1070,7 +971,6 @@ if (this.mag < 1e21 && this.mag > 1e-7 || this.mag === 0) { return (this.sign * this.mag).toFixed(places); } - return decimalPlaces(this.m, places) + "e" + decimalPlaces(this.e, places); } else if (this.layer === 1) { return decimalPlaces(this.m, places) + "e" + decimalPlaces(this.e, places); @@ -1102,10 +1002,10 @@ key: "negated", value: function negated() { return this.neg(); - } // public sign () { + } + // public sign () { // return this.sign; // } - }, { key: "sgn", value: function sgn() { @@ -1117,11 +1017,9 @@ if (this.mag < 0) { return Decimal.dZero; } - if (this.layer === 0) { return FC(this.sign, 0, Math.round(this.mag)); } - return this; } }, { @@ -1130,11 +1028,9 @@ if (this.mag < 0) { return Decimal.dZero; } - if (this.layer === 0) { return FC(this.sign, 0, Math.floor(this.mag)); } - return this; } }, { @@ -1143,11 +1039,9 @@ if (this.mag < 0) { return Decimal.dZero; } - if (this.layer === 0) { return FC(this.sign, 0, Math.ceil(this.mag)); } - return this; } }, { @@ -1156,47 +1050,39 @@ if (this.mag < 0) { return Decimal.dZero; } - if (this.layer === 0) { return FC(this.sign, 0, Math.trunc(this.mag)); } - return this; } }, { key: "add", value: function add(value) { - var decimal = D(value); //inf/nan check - + var decimal = D(value); + //inf/nan check if (!Number.isFinite(this.layer)) { return this; } - if (!Number.isFinite(decimal.layer)) { return decimal; - } //Special case - if one of the numbers is 0, return the other number. - - + } + //Special case - if one of the numbers is 0, return the other number. if (this.sign === 0) { return decimal; } - if (decimal.sign === 0) { return this; - } //Special case - Adding a number to its negation produces 0, no matter how large. - - + } + //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) { return FC_NN(0, 0, 0); } - var a; - var b; //Special case: If one of the numbers is layer 2 or higher, just take the bigger number. - + var b; + //Special case: If one of the numbers is layer 2 or higher, just take the bigger number. if (this.layer >= 2 || decimal.layer >= 2) { return this.maxabs(decimal); } - if (Decimal.cmpabs(this, decimal) > 0) { a = this; b = decimal; @@ -1204,18 +1090,15 @@ a = decimal; b = this; } - if (a.layer === 0 && b.layer === 0) { return Decimal.fromNumber(a.sign * a.mag + b.sign * b.mag); } - var layera = a.layer * Math.sign(a.mag); - var layerb = b.layer * Math.sign(b.mag); //If one of the numbers is 2+ layers higher than the other, just take the bigger number. - + var layerb = b.layer * Math.sign(b.mag); + //If one of the numbers is 2+ layers higher than the other, just take the bigger number. if (layera - layerb >= 2) { return a; } - if (layera === 0 && layerb === -1) { if (Math.abs(b.mag - Math.log10(a.mag)) > MAX_SIGNIFICANT_DIGITS) { return a; @@ -1225,26 +1108,20 @@ return FC(Math.sign(mantissa), 1, b.mag + Math.log10(Math.abs(mantissa))); } } - if (layera === 1 && layerb === 0) { if (Math.abs(a.mag - Math.log10(b.mag)) > MAX_SIGNIFICANT_DIGITS) { return a; } else { var _magdiff = Math.pow(10, a.mag - Math.log10(b.mag)); - var _mantissa = b.sign + a.sign * _magdiff; - return FC(Math.sign(_mantissa), 1, Math.log10(b.mag) + Math.log10(Math.abs(_mantissa))); } } - if (Math.abs(a.mag - b.mag) > MAX_SIGNIFICANT_DIGITS) { return a; } else { var _magdiff2 = Math.pow(10, a.mag - b.mag); - var _mantissa2 = b.sign + a.sign * _magdiff2; - return FC(Math.sign(_mantissa2), 1, b.mag + Math.log10(Math.abs(_mantissa2))); } } @@ -1271,29 +1148,25 @@ }, { key: "mul", value: function mul(value) { - var decimal = D(value); //inf/nan check - + var decimal = D(value); + //inf/nan check if (!Number.isFinite(this.layer)) { return this; } - if (!Number.isFinite(decimal.layer)) { return decimal; - } //Special case - if one of the numbers is 0, return 0. - - + } + //Special case - if one of the numbers is 0, return 0. if (this.sign === 0 || decimal.sign === 0) { return FC_NN(0, 0, 0); - } //Special case - Multiplying a number by its own reciprocal yields +/- 1, no matter how large. - - + } + //Special case - Multiplying a number by its own reciprocal yields +/- 1, no matter how large. if (this.layer === decimal.layer && this.mag === -decimal.mag) { return FC_NN(this.sign * decimal.sign, 0, 1); } - var a; - var b; //Which number is bigger in terms of its multiplicative distance from 1? - + 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; @@ -1301,35 +1174,27 @@ a = decimal; b = this; } - if (a.layer === 0 && b.layer === 0) { return Decimal.fromNumber(a.sign * b.sign * a.mag * b.mag); - } //Special case: If one of the numbers is layer 3 or higher or one of the numbers is 2+ layers bigger than the other, just take the bigger number. - - + } + //Special case: If one of the numbers is layer 3 or higher or one of the numbers is 2+ layers bigger than the other, just take the bigger number. if (a.layer >= 3 || a.layer - b.layer >= 2) { return FC(a.sign * b.sign, a.layer, a.mag); } - if (a.layer === 1 && b.layer === 0) { return FC(a.sign * b.sign, 1, a.mag + Math.log10(b.mag)); } - if (a.layer === 1 && b.layer === 1) { return FC(a.sign * b.sign, 1, a.mag + b.mag); } - if (a.layer === 2 && b.layer === 1) { var newmag = FC(Math.sign(a.mag), a.layer - 1, Math.abs(a.mag)).add(FC(Math.sign(b.mag), b.layer - 1, Math.abs(b.mag))); return FC(a.sign * b.sign, newmag.layer + 1, newmag.sign * newmag.mag); } - if (a.layer === 2 && b.layer === 2) { var _newmag = FC(Math.sign(a.mag), a.layer - 1, Math.abs(a.mag)).add(FC(Math.sign(b.mag), b.layer - 1, Math.abs(b.mag))); - return FC(a.sign * b.sign, _newmag.layer + 1, _newmag.sign * _newmag.mag); } - throw Error("Bad arguments to mul: " + this + ", " + value); } }, { @@ -1384,23 +1249,53 @@ value: function reciprocate() { return this.recip(); } + //Taken from OmegaNum.js, with a couple touch-ups + //"Truncated division" modulo, like JavaScript's % + }, { + key: "mod", + value: function mod(value) { + var decimal = D(value).abs(); + if (decimal.eq(Decimal.dZero)) return Decimal.dZero; + 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 + if (isFinite(num_this) && isFinite(num_decimal) && num_this != 0 && num_decimal != 0) { + return new Decimal(num_this % num_decimal); + } + if (this.sub(decimal).eq(this)) { + //decimal is too small to register to this + return Decimal.dZero; + } + if (decimal.sub(this).eq(decimal)) { + //this is too small to register to decimal + return this; + } + if (this.sign == -1) return this.abs().mod(decimal).neg(); + return this.sub(this.div(decimal).floor().mul(decimal)); + } + }, { + key: "modulo", + value: function modulo(value) { + return this.mod(value); + } + }, { + key: "modular", + value: function modular(value) { + return this.mod(value); + } /** * -1 for less than value, 0 for equals value, 1 for greater than value */ - }, { key: "cmp", value: function cmp(value) { var decimal = D(value); - if (this.sign > decimal.sign) { return 1; } - if (this.sign < decimal.sign) { return -1; } - return this.sign * this.cmpabs(value); } }, { @@ -1409,23 +1304,18 @@ var decimal = D(value); var layera = this.mag > 0 ? this.layer : -this.layer; var layerb = decimal.mag > 0 ? decimal.layer : -decimal.layer; - if (layera > layerb) { return 1; } - if (layera < layerb) { return -1; } - if (this.mag > decimal.mag) { return 1; } - if (this.mag < decimal.mag) { return -1; } - return 0; } }, { @@ -1444,11 +1334,9 @@ function isFinite() { return _isFinite2.apply(this, arguments); } - isFinite.toString = function () { return _isFinite2.toString(); }; - return isFinite; }(function () { return isFinite(this.sign) && isFinite(this.layer) && isFinite(this.mag); @@ -1549,37 +1437,29 @@ * For example, if you put in 1e-9, then any number closer to the * larger number than (larger number)*1e-9 will be considered equal. */ - }, { key: "eq_tolerance", value: function eq_tolerance(value, tolerance) { var decimal = D(value); // https://stackoverflow.com/a/33024979 - if (tolerance == null) { tolerance = 1e-7; - } //Numbers that are too far away are never close. - - + } + //Numbers that are too far away are never close. if (this.sign !== decimal.sign) { return false; } - if (Math.abs(this.layer - decimal.layer) > 1) { return false; - } // return abs(a-b) <= tolerance * max(abs(a), abs(b)) - - + } + // return abs(a-b) <= tolerance * max(abs(a), abs(b)) var magA = this.mag; var magB = decimal.mag; - if (this.layer > decimal.layer) { magB = f_maglog10(magB); } - if (this.layer < decimal.layer) { magA = f_maglog10(magA); } - return Math.abs(magA - magB) <= tolerance * Math.max(Math.abs(magA), Math.abs(magB)); } }, { @@ -1627,7 +1507,6 @@ if (this.lt(Decimal.dZero)) { return Decimal.dZero; } - return this.log10(); } }, { @@ -1656,21 +1535,17 @@ key: "log", value: function log(base) { base = D(base); - if (this.sign <= 0) { return Decimal.dNaN; } - if (base.sign <= 0) { return Decimal.dNaN; } - if (base.sign === 1 && base.layer === 0 && base.mag === 1) { return Decimal.dNaN; } else if (this.layer === 0 && base.layer === 0) { return FC(this.sign, 0, Math.log(this.mag) / Math.log(base.mag)); } - return Decimal.div(this.log10(), base.log10()); } }, { @@ -1713,39 +1588,32 @@ value: function pow(value) { var decimal = D(value); var a = this; - var b = decimal; //special case: if a is 0, then return 0 (UNLESS b is 0, then return 1) - + var b = 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; - } //special case: if a is 1, then return 1 - - + } + //special case: if a is 1, then return 1 if (a.sign === 1 && a.layer === 0 && a.mag === 1) { return a; - } //special case: if b is 0, then return 1 - - + } + //special case: if b is 0, then return 1 if (b.sign === 0) { return FC_NN(1, 0, 1); - } //special case: if b is 1, then return a - - + } + //special case: if b is 1, then return a if (b.sign === 1 && b.layer === 0 && b.mag === 1) { return a; } - var result = a.absLog10().mul(b).pow10(); - if (this.sign === -1) { if (Math.abs(b.toNumber() % 2) % 2 === 1) { return result.neg(); } else if (Math.abs(b.toNumber() % 2) % 2 === 0) { return result; } - return Decimal.dNaN; } - return result; } }, { @@ -1760,13 +1628,11 @@ */ if (!Number.isFinite(this.layer) || !Number.isFinite(this.mag)) { return Decimal.dNaN; - } - - var a = this; //handle layer 0 case - if no precision is lost just use Math.pow, else promote one layer - + } + var a = 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); - if (Number.isFinite(newmag) && Math.abs(newmag) >= 0.1) { return FC(1, 0, newmag); } else { @@ -1776,18 +1642,15 @@ a = FC_NN(a.sign, a.layer + 1, Math.log10(a.mag)); } } - } //handle all 4 layer 1+ cases individually - - + } + //handle all 4 layer 1+ cases individually if (a.sign > 0 && a.mag >= 0) { return FC(a.sign, a.layer + 1, a.mag); } - if (a.sign < 0 && a.mag >= 0) { return FC(-a.sign, a.layer + 1, -a.mag); - } //both the negative mag cases are identical: one +/- rounding error - - + } + //both the negative mag cases are identical: one +/- rounding error return Decimal.dOne; } }, { @@ -1813,8 +1676,8 @@ } else { return Decimal.exp(this); } - } //from HyperCalc source code - + } + //from HyperCalc source code }, { key: "gamma", value: function gamma() { @@ -1824,10 +1687,8 @@ if (this.lt(FC_NN(1, 0, 24))) { return Decimal.fromNumber(f_gamma(this.sign * this.mag)); } - var t = this.mag - 1; var l = 0.9189385332046727; //0.5*Math.log(2*Math.PI) - l = l + (t + 0.5) * Math.log(t); l = l - t; var n2 = t * t; @@ -1835,21 +1696,17 @@ var lm = 12 * np; var adj = 1 / lm; var l2 = l + adj; - if (l2 === l) { return Decimal.exp(l); } - l = l2; np = np * n2; lm = 360 * np; adj = 1 / lm; l2 = l - adj; - if (l2 === l) { return Decimal.exp(l); } - l = l2; np = np * n2; lm = 1260 * np; @@ -1877,7 +1734,6 @@ if (this.mag < 0) { return Decimal.dOne; } - if (this.layer === 0 && this.mag <= 709.7) { return Decimal.fromNumber(Math.exp(this.sign * this.mag)); } else if (this.layer === 0) { @@ -1916,46 +1772,41 @@ key: "cbrt", value: function cbrt() { return this.pow(1 / 3); - } //Tetration/tetrate: The result of exponentiating 'this' to 'this' 'height' times in a row. https://en.wikipedia.org/wiki/Tetration + } + //Tetration/tetrate: The result of exponentiating 'this' to 'this' 'height' times in a row. https://en.wikipedia.org/wiki/Tetration //If payload != 1, then this is 'iterated exponentiation', the result of exping (payload) to base (this) (height) times. https://andydude.github.io/tetration/archives/tetration2/ident.html //Works with negative and positive real heights. - }, { key: "tetrate", value: function tetrate() { 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; //x^^1 == x if (height === 1) { return Decimal.pow(this, payload); - } //x^^0 == 1 - - + } + //x^^0 == 1 if (height === 0) { return new Decimal(payload); - } //1^^x == 1 - - + } + //1^^x == 1 if (this.eq(Decimal.dOne)) { return Decimal.dOne; - } //-1^^x == -1 - - + } + //-1^^x == -1 if (this.eq(-1)) { return Decimal.pow(this, payload); } - if (height === Number.POSITIVE_INFINITY) { - var this_num = this.toNumber(); //within the convergence range? - + var this_num = this.toNumber(); + //within the convergence range? if (this_num <= 1.44466786100976613366 && this_num >= 0.06598803584531253708) { //hotfix for the very edge of the number range not being handled properly if (this_num > 1.444667861009099) { return Decimal.fromNumber(Math.E); - } //Formula for infinite height power tower. - - + } + //Formula for infinite height power tower. var negln = Decimal.ln(this).neg(); return negln.lambertw().div(negln); } else if (this_num > 1.44466786100976613366) { @@ -1967,259 +1818,232 @@ //this_num < 0: quickly becomes a complex number return Decimal.dNaN; } - } //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 + } + //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 //using the linear approximation for height (TODO: don't know a better way to calculate it ATM, but it wouldn't surprise me if it's just NaN) - - if (this.eq(Decimal.dZero)) { var result = Math.abs((height + 1) % 2); - if (result > 1) { result = 2 - result; } - return Decimal.fromNumber(result); } - if (height < 0) { - return Decimal.iteratedlog(payload, this, -height); + return Decimal.iteratedlog(payload, this, -height, linear); } - payload = D(payload); var oldheight = height; height = Math.trunc(height); var fracheight = oldheight - height; - - if (this.gt(Decimal.dZero) && this.lte(1.44466786100976613366)) { + 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) { var old_payload = payload; - payload = this.pow(payload); //stop early if we converge - + payload = this.pow(payload); + //stop early if we converge if (old_payload.eq(payload)) { return payload; } } - - if (fracheight != 0) { + if (fracheight != 0 || oldheight > 10000) { var next_payload = this.pow(payload); - return payload.mul(1 - fracheight).add(next_payload.mul(fracheight)); + 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)); + } } - return payload; - } //TODO: base < 0, but it's hard for me to reason about (probably all non-integer heights are NaN automatically?) - - + } + //TODO: base < 0, but it's hard for me to reason about (probably all non-integer heights are NaN automatically?) if (fracheight !== 0) { if (payload.eq(Decimal.dOne)) { + //If (linear), use linear approximation even for bases <= 10 //TODO: for bases above 10, revert to old linear approximation until I can think of something better - if (this.gt(10)) { + if (this.gt(10) || linear) { payload = this.pow(fracheight); } else { - payload = Decimal.fromNumber(Decimal.tetrate_critical(this.toNumber(), fracheight)); //TODO: until the critical section grid can handle numbers below 2, scale them to the base + payload = Decimal.fromNumber(Decimal.tetrate_critical(this.toNumber(), fracheight)); + //TODO: until the critical section grid can handle numbers below 2, scale them to the base //TODO: maybe once the critical section grid has very large bases, this math can be appropriate for them too? I'll think about it - if (this.lt(2)) { payload = payload.sub(1).mul(this.minus(1)).plus(1); } } } else { if (this.eq(10)) { - payload = payload.layeradd10(fracheight); + payload = payload.layeradd10(fracheight, linear); } else { - payload = payload.layeradd(fracheight, this); + payload = payload.layeradd(fracheight, this, linear); } } } - for (var _i = 0; _i < height; ++_i) { - payload = this.pow(payload); //bail if we're NaN - + payload = this.pow(payload); + //bail if we're NaN if (!isFinite(payload.layer) || !isFinite(payload.mag)) { return payload.normalize(); - } //shortcut - - + } + //shortcut if (payload.layer - this.layer > 3) { return FC_NN(payload.sign, payload.layer + (height - _i - 1), payload.mag); - } //give up after 10000 iterations if nothing is happening - - + } + //give up after 10000 iterations if nothing is happening if (_i > 10000) { return payload; } } - return payload; - } //iteratedexp/iterated exponentiation: - all cases handled in tetrate, so just call it - + } + //iteratedexp/iterated exponentiation: - all cases handled in tetrate, so just call it }, { key: "iteratedexp", value: function iteratedexp() { 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); - return this.tetrate(height, payload); - } //iterated log/repeated log: The result of applying log(base) 'times' times in a row. Approximately equal to subtracting (times) from the number's slog representation. Equivalent to tetrating to a negative height. + var linear = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + return this.tetrate(height, payload, linear); + } + //iterated log/repeated log: The result of applying log(base) 'times' times in a row. Approximately equal to subtracting (times) from the number's slog representation. Equivalent to tetrating to a negative height. //Works with negative and positive real heights. - }, { key: "iteratedlog", value: function iteratedlog() { var base = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 10; var times = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; - + var linear = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; if (times < 0) { - return Decimal.tetrate(base, -times, this); + return Decimal.tetrate(base, -times, this, linear); } - base = D(base); var result = Decimal.fromDecimal(this); var fulltimes = times; times = Math.trunc(times); var fraction = fulltimes - times; - if (result.layer - base.layer > 3) { var layerloss = Math.min(times, result.layer - base.layer - 3); times -= layerloss; result.layer -= layerloss; } - for (var i = 0; i < times; ++i) { - result = result.log(base); //bail if we're NaN - + result = result.log(base); + //bail if we're NaN if (!isFinite(result.layer) || !isFinite(result.mag)) { return result.normalize(); - } //give up after 10000 iterations if nothing is happening - - + } + //give up after 10000 iterations if nothing is happening if (i > 10000) { return result; } - } //handle fractional part - - + } + //handle fractional part if (fraction > 0 && fraction < 1) { if (base.eq(10)) { - result = result.layeradd10(-fraction); + result = result.layeradd10(-fraction, linear); } else { - result = result.layeradd(-fraction, base); + result = result.layeradd(-fraction, base, linear); } } - return result; - } //Super-logarithm, one of tetration's inverses, tells you what size power tower you'd have to tetrate base to to get number. By definition, will never be higher than 1.8e308 in break_eternity.js, since a power tower 1.8e308 numbers tall is the largest representable number. + } + //Super-logarithm, one of tetration's inverses, tells you what size power tower you'd have to tetrate base to to get number. By definition, will never be higher than 1.8e308 in break_eternity.js, since a power tower 1.8e308 numbers tall is the largest representable number. // https://en.wikipedia.org/wiki/Super-logarithm // NEW: Accept a number of iterations, and use binary search to, after making an initial guess, hone in on the true value, assuming tetration as the ground truth. - }, { key: "slog", value: function slog() { var base = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 10; var iterations = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100; + var linear = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; var step_size = 0.001; var has_changed_directions_once = false; var previously_rose = false; - var result = this.slog_internal(base).toNumber(); - + var result = this.slog_internal(base, linear).toNumber(); for (var i = 1; i < iterations; ++i) { - var new_decimal = new Decimal(base).tetrate(result); + var new_decimal = new Decimal(base).tetrate(result, Decimal.dOne, linear); var currently_rose = new_decimal.gt(this); - if (i > 1) { if (previously_rose != currently_rose) { has_changed_directions_once = true; } } - previously_rose = currently_rose; - if (has_changed_directions_once) { step_size /= 2; } else { step_size *= 2; } - step_size = Math.abs(step_size) * (currently_rose ? -1 : 1); result += step_size; - if (step_size === 0) { break; } } - return Decimal.fromNumber(result); } }, { key: "slog_internal", value: function slog_internal() { var base = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 10; - base = D(base); //special cases: + var linear = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + base = D(base); + //special cases: //slog base 0 or lower is NaN - if (base.lte(Decimal.dZero)) { return Decimal.dNaN; - } //slog base 1 is NaN - - + } + //slog base 1 is NaN if (base.eq(Decimal.dOne)) { return Decimal.dNaN; - } //need to handle these small, wobbling bases specially - - + } + //need to handle these small, wobbling bases specially if (base.lt(Decimal.dOne)) { if (this.eq(Decimal.dOne)) { return Decimal.dZero; } - if (this.eq(Decimal.dZero)) { return Decimal.dNegOne; - } //0 < this < 1: ambiguous (happens multiple times) + } + //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; - } //slog_n(0) is -1 - - + } + //slog_n(0) is -1 if (this.mag < 0 || this.eq(Decimal.dZero)) { return Decimal.dNegOne; } - var result = 0; var copy = Decimal.fromDecimal(this); - if (copy.layer - base.layer > 3) { var layerloss = copy.layer - base.layer - 3; result += layerloss; copy.layer -= layerloss; } - for (var i = 0; i < 100; ++i) { if (copy.lt(Decimal.dZero)) { copy = Decimal.pow(base, copy); result -= 1; } else if (copy.lte(Decimal.dOne)) { - return Decimal.fromNumber(result + Decimal.slog_critical(base.toNumber(), copy.toNumber())); + if (linear) return Decimal.fromNumber(result + copy.toNumber() - 1);else return Decimal.fromNumber(result + Decimal.slog_critical(base.toNumber(), copy.toNumber())); } else { result += 1; copy = Decimal.log(copy, base); } } - return Decimal.fromNumber(result); - } //background info and tables of values for critical functions taken here: https://github.com/Patashu/break_eternity.js/issues/22 - + } + //background info and tables of values for critical functions taken here: https://github.com/Patashu/break_eternity.js/issues/22 }, { key: "layeradd10", - value: //Function for adding/removing layers from a Decimal, even fractional layers (e.g. its slog10 representation). + value: + //Function for adding/removing layers from a Decimal, even fractional layers (e.g. its slog10 representation). //Moved this over to use the same critical section as tetrate/slog. function layeradd10(diff) { + var linear = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; diff = Decimal.fromValue_noAlloc(diff).toNumber(); var result = Decimal.fromDecimal(this); - if (diff >= 1) { //bug fix: if result is very smol (mag < 0, layer > 0) turn it into 0 first if (result.mag < 0 && result.layer > 0) { @@ -2231,87 +2055,75 @@ result.sign = 1; result.mag = -result.mag; } - var layeradd = Math.trunc(diff); diff -= layeradd; result.layer += layeradd; } - if (diff <= -1) { var _layeradd = Math.trunc(diff); - diff -= _layeradd; result.layer += _layeradd; - if (result.layer < 0) { for (var i = 0; i < 100; ++i) { result.layer++; result.mag = Math.log10(result.mag); - if (!isFinite(result.mag)) { //another bugfix: if we hit -Infinity mag, then we should return negative infinity, not 0. 0.layeradd10(-1) h its this if (result.sign === 0) { result.sign = 1; - } //also this, for 0.layeradd10(-2) - - + } + //also this, for 0.layeradd10(-2) if (result.layer < 0) { result.layer = 0; } - return result.normalize(); } - if (result.layer >= 0) { break; } } } } - while (result.layer < 0) { result.layer++; result.mag = Math.log10(result.mag); - } //bugfix: before we normalize: if we started with 0, we now need to manually fix a layer ourselves! - - + } + //bugfix: before we normalize: if we started with 0, we now need to manually fix a layer ourselves! if (result.sign === 0) { result.sign = 1; - if (result.mag === 0 && result.layer >= 1) { result.layer -= 1; result.mag = 1; } } - - result.normalize(); //layeradd10: like adding 'diff' to the number's slog(base) representation. Very similar to tetrate base 10 and iterated log base 10. Also equivalent to adding a fractional amount to the number's layer in its break_eternity.js representation. - + result.normalize(); + //layeradd10: like adding 'diff' to the number's slog(base) representation. Very similar to tetrate base 10 and iterated log base 10. Also equivalent to adding a fractional amount to the number's layer in its break_eternity.js representation. if (diff !== 0) { - return result.layeradd(diff, 10); //safe, only calls positive height 1 payload tetration, slog and log + return result.layeradd(diff, 10, linear); //safe, only calls positive height 1 payload tetration, slog and log } return result; - } //layeradd: like adding 'diff' to the number's slog(base) representation. Very similar to tetrate base 'base' and iterated log base 'base'. - + } + //layeradd: like adding 'diff' to the number's slog(base) representation. Very similar to tetrate base 'base' and iterated log base 'base'. }, { 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 slogdest = slogthis + diff; - if (slogdest >= 0) { - return Decimal.tetrate(base, slogdest); + return Decimal.tetrate(base, slogdest, Decimal.dOne, linear); } else if (!Number.isFinite(slogdest)) { return Decimal.dNaN; } else if (slogdest >= -1) { - return Decimal.log(Decimal.tetrate(base, slogdest + 1), base); + return Decimal.log(Decimal.tetrate(base, slogdest + 1, Decimal.dOne, linear), base); } else { - return Decimal.log(Decimal.log(Decimal.tetrate(base, slogdest + 2), base), base); + return Decimal.log(Decimal.log(Decimal.tetrate(base, slogdest + 2, Decimal.dOne, linear), base), base); } - } //The Lambert W function, also called the omega function or product logarithm, is the solution W(x) === x*e^x. + } + //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 //Some special values, for testing: https://en.wikipedia.org/wiki/Lambert_W_function#Special_values - }, { key: "lambertw", value: function lambertw() { @@ -2326,78 +2138,346 @@ } else if (this.layer === 2) { return d_lambertw(this); } - if (this.layer >= 3) { return FC_NN(this.sign, this.layer - 1, this.mag); } - throw "Unhandled behavior in lambertw()"; - } //The super square-root function - what number, tetrated to height 2, equals this? + } + //The super square-root function - what number, tetrated to height 2, equals this? //Other sroots are possible to calculate probably through guess and check methods, this one is easy though. // https://en.wikipedia.org/wiki/Tetration#Super-root - }, { key: "ssqrt", value: function ssqrt() { if (this.sign == 1 && this.layer >= 3) { return FC_NN(this.sign, this.layer - 1, this.mag); } - var lnx = this.ln(); return lnx.div(lnx.lambertw()); - } //Pentation/pentate: The result of tetrating 'height' times in a row. An absurdly strong operator - Decimal.pentate(2, 4.28) and Decimal.pentate(10, 2.37) are already too huge for break_eternity.js! - // https://en.wikipedia.org/wiki/Pentation + } + //Super-root, one of tetration's inverses - what number, tetrated to height (height), equals this? + //Only works with the linear approximation, because I don't know the structure of non-linear tetrations for inputs < 1 + //TODO: Optimize this like how slog is optimized + }, { + key: "linear_sroot", + value: function linear_sroot(degree) { + //1st-degree super root just returns its input + if (degree == 1) { + return this; + } + if (this.eq(Decimal.dInf)) { + return Decimal.dInf; + } + if (!this.isFinite()) { + return Decimal.dNaN; + } + //ssqrt handles square super-root faster + if (degree == 2) { + try { + //ssqrt uses lambertw which throws an error if the number is too small + return this.ssqrt(); + } catch (_a) { + return Decimal.dNaN; + } + } + //Using linear approximation, x^^n = x^n if 0 < n < 1 + if (degree > 0 && degree < 1) { + return this.root(degree); + } + //Using the linear approximation, there actually is a single solution for super roots with -2 < degree <= -1 + if (degree > -2 && degree < -1) { + return Decimal.fromNumber(degree).add(2).pow(this.recip()); + } + //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; + } + //Infinite degree super-root is x^(1/x) between 1/e <= x <= e, undefined otherwise + if (degree == Number.POSITIVE_INFINITY) { + var this_num = this.toNumber(); + if (this_num < Math.E && this_num > _EXPN1) { + return this.pow(this.recip()); + } else { + return Decimal.dNaN; + } + } + //Special case: any super-root of 1 is 1 + if (this.eq(1)) { + return Decimal.dOne; + } + //TODO: base < 0 (It'll probably be NaN anyway) + if (this.lt(0)) { + return Decimal.dNaN; + } + //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; + } + //this > 1 + if (this.gt(1)) { + //Uses guess-and-check to find the super-root. + //If this > 10^^(degree), then the answer is under iteratedlog(10, degree - 1): for example, ssqrt(x) < log(x, 10) as long as x > 10^10, and linear_sroot(x, 3) < log(log(x, 10), 10) as long as x > 10^10^10 + //On the other hand, if this < 10^^(degree), then clearly the answer is less than 10 + //Since the answer could be a higher-layered number itself (whereas slog's maximum is 1.8e308), the guess-and-check is scaled to the layer of the upper bound, so the guess is set to the average of some higher-layer exponents of the bounds rather than the bounds itself (as taking plain averages on tetrational-scale numbers would go nowhere) + var upperBound = Decimal.dTen; + if (this.gte(Decimal.tetrate(10, degree, 1, true))) { + upperBound = this.iteratedlog(10, degree - 1, true); + } + if (degree <= 1) { + upperBound = this.root(degree); + } + var lower = Decimal.dZero; //This is zero rather than one because we might be on a higher layer, so the lower bound might actually some 10^10^10...^0 + var layer = upperBound.layer; + var upper = upperBound.iteratedlog(10, layer, true); + var previous = upper; + var guess = upper.div(2); + var loopGoing = true; + while (loopGoing) { + guess = lower.add(upper).div(2); + if (Decimal.iteratedexp(10, layer, guess, true).tetrate(degree, 1, true).gt(this)) upper = guess;else lower = guess; + if (guess.eq(previous)) loopGoing = false;else previous = guess; + } + return Decimal.iteratedexp(10, layer, guess, true); + } + //0 < this < 1 + else { + //A tetration of decimal degree can potentially have three different portions, as shown at https://www.desmos.com/calculator/ayvqks6mxa, which is a graph of x^^2.05: + //The portion where the function is increasing, extending from a minimum (which may be at x = 0 or at some x between 0 and 1) up to infinity (I'll call this the "increasing" range) + //The portion where the function is decreasing (I'll call this the "decreasing" range) + //A small, steep increasing portion very close to x = 0 (I'll call this the "zero" range) + //If ceiling(degree) is even, then the tetration will either be strictly increasing, or it will have the increasing and decreasing ranges, but not the zero range (because if ceiling(degree) is even, 0^^degree == 1). + //If ceiling(degree) is odd, then the tetration will either be strictly increasing, or it will have all three ranges (because if ceiling(degree) is odd, 0^^degree == 0). + //The existence of these ranges means that a super-root could potentially have two or three valid answers. + //Out of these, we'd prefer the increasing range value if it exists, otherwise we'll take the zero range value (it can't have a decreasing range value if it doesn't have an increasing range value) if the zero range exists. + //It's possible to identify which range that "this" is in: + //If the tetration is decreasing at that point, the point is in the decreasing range. + //If the tetration is increasing at that point and ceiling(degree) is even, the point is in the increasing range since there is no zero range. + //If the tetration is increasing at that point and ceiling(degree) is odd, look at the second derivative at that point. If the second derivative is positive, the point is in the increasing range. If the second derivative is negative, the point is the zero range. + //We need to find the local minimum (separates decreasing and increasing ranges) and the local maximum (separates zero and decreasing ranges). + //(stage) is which stage of the loop we're in: stage 1 is finding the minimum, stage 2 means we're between the stages, and stage 3 is finding the maximum. + //The boundary between the decreasing range and the zero range can be very small, so we want to use layer -1 numbers. Therefore, all numbers involved are log10(recip()) of their actual values. + var stage = 1; + var minimum = FC(1, 10, 1); + var maximum = FC(1, 10, 1); + var _lower = FC(1, 10, 1); //eeeeeeeee-10, which is effectively 0; I would use Decimal.dInf but its reciprocal is NaN + var _upper = FC(1, 1, -16); //~ 1 - 1e-16 + var prevspan = Decimal.dZero; + var difference = FC(1, 10, 1); + var _upperBound = _upper.pow10().recip(); + var distance = Decimal.dZero; + var prevPoint = _upperBound; + var nextPoint = _upperBound; + var evenDegree = Math.ceil(degree) % 2 == 0; + var range = 0; + var lastValid = FC(1, 10, 1); + var infLoopDetector = false; + var previousUpper = Decimal.dZero; + var decreasingFound = false; + while (stage < 4) { + if (stage == 2) { + //The minimum has been found. If ceiling(degree) is even, there's no zero range and thus no local maximum, so end the loop here. Otherwise, begin finding the maximum. + if (evenDegree) break;else { + _lower = FC(1, 10, 1); + _upper = minimum; + stage = 3; + difference = FC(1, 10, 1); + lastValid = FC(1, 10, 1); + } + } + infLoopDetector = false; + while (_upper.neq(_lower)) { + previousUpper = _upper; + if (_upper.pow10().recip().tetrate(degree, 1, true).eq(1) && _upper.pow10().recip().lt(0.4)) { + _upperBound = _upper.pow10().recip(); + prevPoint = _upper.pow10().recip(); + nextPoint = _upper.pow10().recip(); + distance = Decimal.dZero; + range = -1; //This would cause problems with degree < 1 in the linear approximation... but those are already covered as a special case + if (stage == 3) lastValid = _upper; + } else if (_upper.pow10().recip().tetrate(degree, 1, true).eq(_upper.pow10().recip()) && !evenDegree && _upper.pow10().recip().lt(0.4)) { + _upperBound = _upper.pow10().recip(); + prevPoint = _upper.pow10().recip(); + nextPoint = _upper.pow10().recip(); + distance = Decimal.dZero; + range = 0; + } else if (_upper.pow10().recip().tetrate(degree, 1, true).eq(_upper.pow10().recip().mul(2).tetrate(degree, 1, true))) { + //If the upper bound is closer to zero than the next point with a discernable tetration, so surely it's in whichever range is closest to zero? + //This won't happen in a strictly increasing tetration, as there x^^degree ~= x as x approaches zero + _upperBound = _upper.pow10().recip(); + prevPoint = Decimal.dZero; + nextPoint = _upperBound.mul(2); + distance = _upperBound; + if (evenDegree) range = -1;else range = 0; + } else { + //We want to use prevspan to find the "previous point" right before the upper bound and the "next point" right after the upper bound, as that will let us approximate derivatives + prevspan = _upper.mul(1.2e-16); + _upperBound = _upper.pow10().recip(); + prevPoint = _upper.add(prevspan).pow10().recip(); + distance = _upperBound.sub(prevPoint); + nextPoint = _upperBound.add(distance); + //...but it's of no use to us while its tetration is equal to upper's tetration, so widen the difference until it's not + //We add prevspan and subtract nextspan because, since upper is log10(recip(upper bound)), the upper bound gets smaller as upper gets larger and vice versa + while (prevPoint.tetrate(degree, 1, true).eq(_upperBound.tetrate(degree, 1, true)) || nextPoint.tetrate(degree, 1, true).eq(_upperBound.tetrate(degree, 1, true)) || prevPoint.gte(_upperBound) || nextPoint.lte(_upperBound)) { + prevspan = prevspan.mul(2); + prevPoint = _upper.add(prevspan).pow10().recip(); + distance = _upperBound.sub(prevPoint); + nextPoint = _upperBound.add(distance); + } + if (stage == 1 && nextPoint.tetrate(degree, 1, true).gt(_upperBound.tetrate(degree, 1, true)) && prevPoint.tetrate(degree, 1, true).gt(_upperBound.tetrate(degree, 1, true)) || stage == 3 && nextPoint.tetrate(degree, 1, true).lt(_upperBound.tetrate(degree, 1, true)) && prevPoint.tetrate(degree, 1, true).lt(_upperBound.tetrate(degree, 1, true))) { + lastValid = _upper; + } + if (nextPoint.tetrate(degree, 1, true).lt(_upperBound.tetrate(degree, 1, true))) { + //Derivative is negative, so we're in decreasing range + range = -1; + } else if (evenDegree) { + //No zero range, so we're in increasing range + range = 1; + } else if (stage == 3 && _upper.gt_tolerance(minimum, 1e-8)) { + //We're already below the minimum, so we can't be in range 1 + range = 0; + } else { + //Number imprecision has left the second derivative somewhat untrustworthy, so we need to expand the bounds to ensure it's correct + while (prevPoint.tetrate(degree, 1, true).eq_tolerance(_upperBound.tetrate(degree, 1, true), 1e-8) || nextPoint.tetrate(degree, 1, true).eq_tolerance(_upperBound.tetrate(degree, 1, true), 1e-8) || prevPoint.gte(_upperBound) || nextPoint.lte(_upperBound)) { + prevspan = prevspan.mul(2); + prevPoint = _upper.add(prevspan).pow10().recip(); + distance = _upperBound.sub(prevPoint); + nextPoint = _upperBound.add(distance); + } + if (nextPoint.tetrate(degree, 1, true).sub(_upperBound.tetrate(degree, 1, true)).lt(_upperBound.tetrate(degree, 1, true).sub(prevPoint.tetrate(degree, 1, true)))) { + //Second derivative is negative, so we're in zero range + range = 0; + } else { + //By process of elimination, we're in increasing range + range = 1; + } + } + } + if (range == -1) decreasingFound = true; + if (stage == 1 && range == 1 || stage == 3 && range != 0) { + //The upper bound is too high + if (_lower.eq(FC(1, 10, 1))) { + _upper = _upper.mul(2); + } else { + var cutOff = false; + if (infLoopDetector && (range == 1 && stage == 1 || range == -1 && stage == 3)) cutOff = true; //Avoids infinite loops from floating point imprecision + _upper = _upper.add(_lower).div(2); + if (cutOff) break; + } + } else { + if (_lower.eq(FC(1, 10, 1))) { + //We've now found an actual lower bound + _lower = _upper; + _upper = _upper.div(2); + } else { + //The upper bound is too low, meaning last time we decreased the upper bound, we should have gone to the other half of the new range instead + var _cutOff = false; + if (infLoopDetector && (range == 1 && stage == 1 || range == -1 && stage == 3)) _cutOff = true; //Avoids infinite loops from floating point imprecision + _lower = _lower.sub(difference); + _upper = _upper.sub(difference); + if (_cutOff) break; + } + } + if (_lower.sub(_upper).div(2).abs().gt(difference.mul(1.5))) infLoopDetector = true; + difference = _lower.sub(_upper).div(2).abs(); + if (_upper.gt("1e18")) break; + if (_upper.eq(previousUpper)) break; //Another infinite loop catcher + } + if (_upper.gt("1e18")) break; + if (!decreasingFound) break; //If there's no decreasing range, then even if an error caused lastValid to gain a value, the minimum can't exist + if (lastValid == FC(1, 10, 1)) { + //Whatever we're searching for, it doesn't exist. If there's no minimum, then there's no maximum either, so either way we can end the loop here. + break; + } + if (stage == 1) minimum = lastValid;else if (stage == 3) maximum = lastValid; + stage++; + } + //Now we have the minimum and maximum, so it's time to calculate the actual super-root. + //First, check if the root is in the increasing range. + _lower = minimum; + _upper = FC(1, 1, -18); + var _previous = _upper; + var _guess = Decimal.dZero; + var _loopGoing = true; + while (_loopGoing) { + 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; + } + //using guess.neq(minimum) led to imprecision errors, so here's a fixed version of that + if (!_guess.eq_tolerance(minimum, 1e-15)) { + return _guess.pow10().recip(); + } else { + //If guess == minimum, we haven't actually found the super-root, the algorithm just kept going down trying to find a super-root that's not in the increasing range. + //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; + } + _lower = FC(1, 10, 1); + _upper = maximum; + _previous = _upper; + _guess = Decimal.dZero; + _loopGoing = true; + while (_loopGoing) { + 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; + } + return _guess.pow10().recip(); + } + } + } + //Pentation/pentate: The result of tetrating 'height' times in a row. An absurdly strong operator - Decimal.pentate(2, 4.28) and Decimal.pentate(10, 2.37) are already too huge for break_eternity.js! + // https://en.wikipedia.org/wiki/Pentation }, { key: "pentate", value: function pentate() { 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); var oldheight = height; height = Math.trunc(height); - var fracheight = oldheight - height; //I have no idea if this is a meaningful approximation for pentation to continuous heights, but it is monotonic and continuous. - + var fracheight = oldheight - height; + //I have no idea if this is a meaningful approximation for pentation to continuous heights, but it is monotonic and continuous. if (fracheight !== 0) { if (payload.eq(Decimal.dOne)) { ++height; payload = Decimal.fromNumber(fracheight); } else { if (this.eq(10)) { - payload = payload.layeradd10(fracheight); + payload = payload.layeradd10(fracheight, linear); } else { - payload = payload.layeradd(fracheight, this); + payload = payload.layeradd(fracheight, this, linear); } } } - for (var i = 0; i < height; ++i) { - payload = this.tetrate(payload.toNumber()); //bail if we're NaN - + payload = this.tetrate(payload.toNumber(), Decimal.dOne, linear); + //bail if we're NaN if (!isFinite(payload.layer) || !isFinite(payload.mag)) { return payload.normalize(); - } //give up after 10 iterations if nothing is happening - - + } + //give up after 10 iterations if nothing is happening if (i > 10) { return payload; } } - return payload; - } // trig functions! - + } + // trig functions! }, { key: "sin", value: function sin() { if (this.mag < 0) { return this; } - if (this.layer === 0) { return Decimal.fromNumber(Math.sin(this.sign * this.mag)); } - return FC_NN(0, 0, 0); } }, { @@ -2406,11 +2486,9 @@ if (this.mag < 0) { return Decimal.dOne; } - if (this.layer === 0) { return Decimal.fromNumber(Math.cos(this.sign * this.mag)); } - return FC_NN(0, 0, 0); } }, { @@ -2419,11 +2497,9 @@ if (this.mag < 0) { return this; } - if (this.layer === 0) { return Decimal.fromNumber(Math.tan(this.sign * this.mag)); } - return FC_NN(0, 0, 0); } }, { @@ -2432,11 +2508,9 @@ if (this.mag < 0) { return this; } - if (this.layer === 0) { return Decimal.fromNumber(Math.asin(this.sign * this.mag)); } - return FC_NN(Number.NaN, Number.NaN, Number.NaN); } }, { @@ -2445,11 +2519,9 @@ if (this.mag < 0) { return Decimal.fromNumber(Math.acos(this.toNumber())); } - if (this.layer === 0) { return Decimal.fromNumber(Math.acos(this.sign * this.mag)); } - return FC_NN(Number.NaN, Number.NaN, Number.NaN); } }, { @@ -2458,11 +2530,9 @@ if (this.mag < 0) { return this; } - if (this.layer === 0) { return Decimal.fromNumber(Math.atan(this.sign * this.mag)); } - return Decimal.fromNumber(Math.atan(this.sign * 1.8e308)); } }, { @@ -2496,26 +2566,22 @@ if (this.abs().gte(1)) { return FC_NN(Number.NaN, Number.NaN, Number.NaN); } - return Decimal.ln(this.add(1).div(Decimal.fromNumber(1).sub(this))).div(2); } /** * Joke function from Realm Grinder */ - }, { key: "ascensionPenalty", value: function ascensionPenalty(ascensions) { if (ascensions === 0) { return this; } - return this.root(Decimal.pow(10, ascensions)); } /** * Joke function from Cookie Clicker. It's 'egg' */ - }, { key: "egg", value: function egg() { @@ -2590,7 +2656,6 @@ * Use `new Decimal(value)` to explicitly create a writeable copy if mutation * is required. */ - }, { key: "fromValue_noAlloc", value: function fromValue_noAlloc(value) { @@ -2598,11 +2663,9 @@ return value; } else if (typeof value === "string") { var cached = Decimal.fromStringCache.get(value); - if (cached !== undefined) { return cached; } - return Decimal.fromString(value); } else if (typeof value === "number") { return Decimal.fromNumber(value); @@ -2728,6 +2791,21 @@ value: function reciprocate(value) { return D(value).reciprocate(); } + }, { + key: "mod", + value: function mod(value, other) { + return D(value).mod(other); + } + }, { + key: "modulo", + value: function modulo(value, other) { + return D(value).modulo(other); + } + }, { + key: "modular", + value: function modular(value, other) { + return D(value).modular(other); + } }, { key: "cmp", value: function cmp(value, other) { @@ -2749,11 +2827,9 @@ function isNaN(_x) { return _isNaN.apply(this, arguments); } - isNaN.toString = function () { return _isNaN.toString(); }; - return isNaN; }(function (value) { value = D(value); @@ -2765,11 +2841,9 @@ function isFinite(_x2) { return _isFinite.apply(this, arguments); } - isFinite.toString = function () { return _isFinite.toString(); }; - return isFinite; }(function (value) { value = D(value); @@ -2995,38 +3069,44 @@ value: function tetrate(value) { var height = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2; var payload = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : FC_NN(1, 0, 1); - return D(value).tetrate(height, payload); + var linear = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; + return D(value).tetrate(height, payload, linear); } }, { key: "iteratedexp", value: function iteratedexp(value) { var height = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2; var payload = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : FC_NN(1, 0, 1); - return D(value).iteratedexp(height, payload); + var linear = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; + return D(value).iteratedexp(height, payload, linear); } }, { key: "iteratedlog", value: function iteratedlog(value) { var base = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 10; var times = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1; - return D(value).iteratedlog(base, times); + var linear = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; + return D(value).iteratedlog(base, times, linear); } }, { key: "layeradd10", value: function layeradd10(value, diff) { - return D(value).layeradd10(diff); + var linear = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + return D(value).layeradd10(diff, linear); } }, { key: "layeradd", value: function layeradd(value, diff) { var base = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 10; - return D(value).layeradd(diff, base); + var linear = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; + return D(value).layeradd(diff, base, linear); } }, { key: "slog", value: function slog(value) { var base = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 10; - return D(value).slog(base); + var linear = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + return D(value).slog(base, 100, linear); } }, { key: "lambertw", @@ -3038,12 +3118,18 @@ value: function ssqrt(value) { return D(value).ssqrt(); } + }, { + key: "linear_sroot", + value: function linear_sroot(value, height) { + return D(value).linear_sroot(height); + } }, { key: "pentate", value: function pentate(value) { var height = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2; var payload = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : FC_NN(1, 0, 1); - return D(value).pentate(height, payload); + var linear = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; + return D(value).pentate(height, payload, linear); } /** * If you're willing to spend 'resourcesAvailable' and want to buy something @@ -3051,7 +3137,6 @@ * multiply by priceRatio, already own currentOwned), how much of it can you buy? * Adapted from Trimps source code. */ - }, { key: "affordGeometricSeries", value: function affordGeometricSeries(resourcesAvailable, priceStart, priceRatio, currentOwned) { @@ -3061,7 +3146,6 @@ * How much resource would it cost to buy (numItems) items if you already have currentOwned, * the initial price is priceStart and it multiplies by priceRatio each purchase? */ - }, { key: "sumGeometricSeries", value: function sumGeometricSeries(numItems, priceStart, priceRatio, currentOwned) { @@ -3072,7 +3156,6 @@ * increasing cost each purchase (start at priceStart, add by priceAdd, already own currentOwned), * how much of it can you buy? */ - }, { key: "affordArithmeticSeries", value: function affordArithmeticSeries(resourcesAvailable, priceStart, priceAdd, currentOwned) { @@ -3083,7 +3166,6 @@ * the initial price is priceStart and it adds priceAdd each purchase? * Adapted from http://www.mathwords.com/a/arithmetic_series.htm */ - }, { key: "sumArithmeticSeries", value: function sumArithmeticSeries(numItems, priceStart, priceAdd, currentOwned) { @@ -3095,7 +3177,6 @@ * From Frozen Cookies: * http://cookieclicker.wikia.com/wiki/Frozen_Cookies_(JavaScript_Add-on)#Efficiency.3F_What.27s_that.3F */ - }, { key: "efficiencyOfPurchase", value: function efficiencyOfPurchase(cost, currentRpS, deltaRpS) { @@ -3109,27 +3190,23 @@ if (Math.random() * 20 < 1) { return FC_NN(0, 0, 0); } - - var randomsign = Math.random() > 0.5 ? 1 : -1; //5% of the time, return 1 or -1 - + var randomsign = Math.random() > 0.5 ? 1 : -1; + //5% of the time, return 1 or -1 if (Math.random() * 20 < 1) { return FC_NN(randomsign, 0, 1); - } //pick a random layer - - + } + //pick a random layer var layer = Math.floor(Math.random() * (maxLayers + 1)); - var randomexp = layer === 0 ? Math.random() * 616 - 308 : Math.random() * 16; //10% of the time, make it a simple power of 10 - + var randomexp = layer === 0 ? Math.random() * 616 - 308 : Math.random() * 16; + //10% of the time, make it a simple power of 10 if (Math.random() > 0.9) { randomexp = Math.trunc(randomexp); } - - var randommag = Math.pow(10, randomexp); //10% of the time, trunc mag - + var randommag = Math.pow(10, randomexp); + //10% of the time, trunc mag if (Math.random() > 0.9) { randommag = Math.trunc(randommag); } - return FC(randomsign, layer, randommag); } }, { @@ -3158,7 +3235,6 @@ key: "sumArithmeticSeries_core", value: function sumArithmeticSeries_core(numItems, priceStart, priceAdd, currentOwned) { var actualStart = priceStart.add(currentOwned.mul(priceAdd)); // (n/2)*(2*a+(n-1)*d) - return numItems.div(2).mul(actualStart.mul(2).plus(numItems.sub(1).mul(priceAdd))); } }, { @@ -3173,7 +3249,6 @@ if (base > 10) { return height - 1; } - return Decimal.critical_section(base, height, critical_slog_values); } }, { @@ -3186,30 +3261,25 @@ value: function critical_section(base, height, grid) { //this part is simple at least, since it's just 0.1 to 0.9 height *= 10; - if (height < 0) { height = 0; } - if (height > 10) { height = 10; - } //have to do this complicated song and dance since one of the critical_headers is Math.E, and in the future I'd like 1.5 as well - - + } + //have to do this complicated song and dance since one of the critical_headers is Math.E, and in the future I'd like 1.5 as well if (base < 2) { base = 2; } - if (base > 10) { base = 10; } - var lower = 0; - var upper = 0; //basically, if we're between bases, we interpolate each bases' relevant values together + var upper = 0; + //basically, if we're between bases, we interpolate each bases' relevant values together //then we interpolate based on what the fractional height is. //accuracy could be improved by doing a non-linear interpolation (maybe), by adding more bases and heights (definitely) but this is AFAIK the best you can get without running some pari.gp or mathematica program to calculate exact values //however, do note http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html can do it for arbitrary heights but not for arbitrary bases (2, e, 10 present) - for (var i = 0; i < critical_headers.length; ++i) { if (critical_headers[i] == base) { // exact match @@ -3224,11 +3294,10 @@ break; } } - - var frac = height - Math.floor(height); //improvement - you get more accuracy (especially around 0.9-1.0) by doing log, then frac, then powing the result + var frac = height - Math.floor(height); + //improvement - you get more accuracy (especially around 0.9-1.0) by doing log, then frac, then powing the result //(we could pre-log the lookup table, but then fractional bases would get Weird) //also, use old linear for slog (values 0 or less in critical section). maybe something else is better but haven't thought about what yet - if (lower <= 0 || upper <= 0) { return lower * (1 - frac) + upper * frac; } else { @@ -3236,7 +3305,6 @@ } } }]); - return Decimal; }(); Decimal.dZero = FC_NN(0, 0, 0); @@ -3249,16 +3317,16 @@ Decimal.dNegInf = FC_NN(-1, Number.NEGATIVE_INFINITY, Number.NEGATIVE_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); // return Decimal; + Decimal.fromStringCache = new LRUCache(DEFAULT_FROM_STRING_CACHE_SIZE); + // return Decimal; // Optimise Decimal aliases. // We can't do this optimisation before Decimal is assigned. - D = Decimal.fromValue_noAlloc; FC = Decimal.fromComponents; - FC_NN = Decimal.fromComponents_noNormalize; // eslint-disable-next-line @typescript-eslint/no-unused-vars - - Decimal.fromMantissaExponent; // eslint-disable-next-line @typescript-eslint/no-unused-vars - + FC_NN = Decimal.fromComponents_noNormalize; + // eslint-disable-next-line @typescript-eslint/no-unused-vars + Decimal.fromMantissaExponent; + // eslint-disable-next-line @typescript-eslint/no-unused-vars Decimal.fromMantissaExponent_noNormalize; return Decimal; diff --git a/break_eternity.min.js b/break_eternity.min.js index 4840df8..6297252 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],h=[[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]],o=[[-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 k.fromValue_noAlloc(t)},m=function(t,e,i){return k.fromComponents(t,e,i)},g=function(t,e,i){return k.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(k.dZero))return t;if(t.eq(k.dOne))return k.fromNumber(y);e=k.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(k.mul(2,e).add(2))))),k.abs(n.sub(e)).lt(k.abs(n).mul(a)))return n;e=n}throw Error("Iteration failed to converge: ".concat(t.toString()))}var k=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)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),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)),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=t,r=e.fromStringCache.get(i);if(void 0!==r)return this.fromDecimal(r);var n=(t=t.replace(",","")).split("^^^");if(2===n.length){var a=parseFloat(n[0]),s=parseFloat(n[1]),u=n[1].split(";"),h=1;if(2===u.length&&(h=parseFloat(u[1]),isFinite(h)||(h=1)),isFinite(a)&&isFinite(s)){var o=e.pentate(a,s,h);return this.sign=o.sign,this.layer=o.layer,this.mag=o.mag,e.fromStringCache.maxSize>=1&&e.fromStringCache.set(i,e.fromDecimal(this)),this}}var g=t.split("^^");if(2===g.length){var f=parseFloat(g[0]),y=parseFloat(g[1]),v=g[1].split(";"),d=1;if(2===v.length&&(d=parseFloat(v[1]),isFinite(d)||(d=1)),isFinite(f)&&isFinite(y)){var k=e.tetrate(f,y,d);return this.sign=k.sign,this.layer=k.layer,this.mag=k.mag,e.fromStringCache.maxSize>=1&&e.fromStringCache.set(i,e.fromDecimal(this)),this}}var p,N,b=t.split("^");if(2===b.length){var M=parseFloat(b[0]),_=parseFloat(b[1]);if(isFinite(M)&&isFinite(_)){var x=e.pow(M,_);return this.sign=x.sign,this.layer=x.layer,this.mag=x.mag,e.fromStringCache.maxSize>=1&&e.fromStringCache.set(i,e.fromDecimal(this)),this}}var F=(t=t.trim().toLowerCase()).split("pt");if(2===F.length){p=10,N=parseFloat(F[0]),F[1]=F[1].replace("(",""),F[1]=F[1].replace(")","");var S=parseFloat(F[1]);if(isFinite(S)||(S=1),isFinite(p)&&isFinite(N)){var w=e.tetrate(p,N,S);return this.sign=w.sign,this.layer=w.layer,this.mag=w.mag,e.fromStringCache.maxSize>=1&&e.fromStringCache.set(i,e.fromDecimal(this)),this}}if(2===(F=t.split("p")).length){p=10,N=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(N)){var I=e.tetrate(p,N,q);return this.sign=I.sign,this.layer=I.layer,this.mag=I.mag,e.fromStringCache.maxSize>=1&&e.fromStringCache.set(i,e.fromDecimal(this)),this}}var E=t.split("e"),C=E.length-1;if(0===C){var z=parseFloat(t);if(isFinite(z))return this.fromNumber(z),e.fromStringCache.size>=1&&e.fromStringCache.set(i,e.fromDecimal(this)),this}else if(1===C){var T=parseFloat(t);if(isFinite(T)&&0!==T)return this.fromNumber(T),e.fromStringCache.maxSize>=1&&e.fromStringCache.set(i,e.fromDecimal(this)),this}var O=t.split("e^");if(2===O.length){this.sign=1,"-"==O[0].charAt(0)&&(this.sign=-1);for(var D="",V=0;V=43&&A<=57||101===A))return this.layer=parseFloat(D),this.mag=parseFloat(O[1].substr(V+1)),this.normalize(),e.fromStringCache.maxSize>=1&&e.fromStringCache.set(i,e.fromDecimal(this)),this;D+=O[1].charAt(V)}}if(C<1)return this.sign=0,this.layer=0,this.mag=0,e.fromStringCache.maxSize>=1&&e.fromStringCache.set(i,e.fromDecimal(this)),this;var P=parseFloat(E[0]);if(0===P)return this.sign=0,this.layer=0,this.mag=0,e.fromStringCache.maxSize>=1&&e.fromStringCache.set(i,e.fromDecimal(this)),this;var Z=parseFloat(E[E.length-1]);if(C>=2){var Y=parseFloat(E[E.length-2]);isFinite(Y)&&(Z*=Math.sign(Y),Z+=c(Y))}if(isFinite(P))if(1===C)this.sign=Math.sign(P),this.layer=1,this.mag=Z+Math.log10(Math.abs(P));else{if(this.sign=Math.sign(P),this.layer=C,2===C){var G=e.mul(m(1,2,Z),l(P));return this.sign=G.sign,this.layer=G.layer,this.mag=G.mag,e.fromStringCache.maxSize>=1&&e.fromStringCache.set(i,e.fromDecimal(this)),this}this.mag=Z}else this.sign="-"===E[0]?-1:1,this.layer=C,this.mag=Z;return this.normalize(),e.fromStringCache.maxSize>=1&&e.fromStringCache.set(i,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 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?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?e.dZero:0===this.layer?m(this.sign,0,Math.floor(this.mag)):this}},{key:"ceil",value:function(){return this.mag<0?e.dZero: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),h=r.sign+i.sign*u;return m(Math.sign(h),1,r.mag+Math.log10(Math.abs(h)))}if(1===a&&0===s){if(Math.abs(i.mag-Math.log10(r.mag))>17)return i;var o=Math.pow(10,i.mag-Math.log10(r.mag)),f=r.sign+i.sign*o;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:"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 h=1/(a=1260*(n*=r));return i+=h,i-=h=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);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 r=this.toNumber();if(r<=1.444667861009766&&r>=.06598803584531254){if(r>1.444667861009099)return e.fromNumber(Math.E);var n=e.ln(this).neg();return n.lambertw().div(n)}return r>1.444667861009766?e.fromNumber(Number.POSITIVE_INFINITY):e.dNaN}if(this.eq(e.dZero)){var a=Math.abs((t+1)%2);return a>1&&(a=2-a),e.fromNumber(a)}if(t<0)return e.iteratedlog(i,this,-t);i=l(i);var s=t,u=s-(t=Math.trunc(t));if(this.gt(e.dZero)&&this.lte(1.444667861009766)){t=Math.min(1e4,t);for(var h=0;h3)return g(i.sign,i.layer+(t-f-1),i.mag);if(f>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);return this.tetrate(t,e)}},{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;if(i<0)return e.tetrate(t,-i,this);t=l(t);var r=e.fromDecimal(this),n=i,a=n-(i=Math.trunc(i));if(r.layer-t.layer>3){var s=Math.min(i,r.layer-t.layer-3);i-=s,r.layer-=s}for(var u=0;u1e4)return r}return a>0&&a<1&&(r=t.eq(10)?r.layeradd10(-a):r.layeradd(-a,t)),r}},{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=.001,n=!1,a=!1,s=this.slog_internal(t).toNumber(),u=1;u1&&a!=o&&(n=!0),a=o,n?r/=2:r*=2,s+=r=Math.abs(r)*(o?-1:1),0===r)break}return e.fromNumber(s)}},{key:"slog_internal",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:10;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 i=0,r=e.fromDecimal(this);if(r.layer-t.layer>3){var n=r.layer-t.layer-3;i+=n,r.layer-=n}for(var a=0;a<100;++a)if(r.lt(e.dZero))r=e.pow(t,r),i-=1;else{if(r.lte(e.dOne))return e.fromNumber(i+e.slog_critical(t.toNumber(),r.toNumber()));i+=1,r=e.log(r,t)}return e.fromNumber(i)}},{key:"layeradd10",value:function(t){t=e.fromValue_noAlloc(t).toNumber();var i=e.fromDecimal(this);if(t>=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 r=Math.trunc(t);t-=r,i.layer+=r}if(t<=-1){var n=Math.trunc(t);if(t-=n,i.layer+=n,i.layer<0)for(var a=0;a<100;++a){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!==t?i.layeradd(t,10):i}},{key:"layeradd",value:function(t,i){var r=this.slog(i).toNumber()+t;return r>=0?e.tetrate(i,r):Number.isFinite(r)?r>=-1?e.log(e.tetrate(i,r+1),i):e.log(e.log(e.tetrate(i,r+2),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(){if(1==this.sign&&this.layer>=3)return g(this.sign,this.layer-1,this.mag);var t=this.ln();return t.div(t.lambertw())}},{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);i=l(i);var r=t,n=r-(t=Math.trunc(t));0!==n&&(i.eq(e.dOne)?(++t,i=e.fromNumber(n)):i=this.eq(10)?i.layeradd10(n):i.layeradd(n,this));for(var a=0;a10)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){return(new e).fromString(t)}},{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:"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);return l(t).tetrate(e,i)}},{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);return l(t).iteratedexp(e,i)}},{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;return l(t).iteratedlog(e,i)}},{key:"layeradd10",value:function(t,e){return l(t).layeradd10(e)}},{key:"layeradd",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:10;return l(t).layeradd(e,i)}},{key:"slog",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:10;return l(t).slog(e)}},{key:"lambertw",value:function(t){return l(t).lambertw()}},{key:"ssqrt",value:function(t){return l(t).ssqrt()}},{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);return l(t).pentate(e,i)}},{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,o)}},{key:"tetrate_critical",value:function(t,i){return e.critical_section(t,i,h)}},{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 h=e-Math.floor(e);return r<=0||n<=0?r*(1-h)+n*h:Math.pow(t,Math.log(r)/Math.log(t)*(1-h)+Math.log(n)/Math.log(t)*h)}}]),e}();return k.dZero=g(0,0,0),k.dOne=g(1,0,1),k.dNegOne=g(-1,0,1),k.dTwo=g(1,0,2),k.dTen=g(1,0,10),k.dNaN=g(Number.NaN,Number.NaN,Number.NaN),k.dInf=g(1,Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY),k.dNegInf=g(-1,Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY),k.dNumberMax=m(1,0,Number.MAX_VALUE),k.dNumberMin=m(1,0,Number.MIN_VALUE),k.fromStringCache=new r(1023),l=k.fromValue_noAlloc,m=k.fromComponents,g=k.fromComponents_noNormalize,k.fromMantissaExponent,k.fromMantissaExponent_noNormalize,k})); +!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}(),a=i((function e(i,r){t(this,e),this.next=void 0,this.prev=void 0,this.key=i,this.value=r})),n=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]],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(t){return p.fromValue_noAlloc(t)},m=function(t,e,i){return p.fromComponents(t,e,i)},g=function(t,e,i){return p.fromComponents_noNormalize(t,e,i)},f=function(t,e){var i=e+1,r=Math.ceil(Math.log10(Math.abs(t))),a=Math.round(t*Math.pow(10,i-r))*Math.pow(10,r-i);return parseFloat(a.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 a=0;a<100;++a){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(p.dZero))return t;if(t.eq(p.dOne))return p.fromNumber(y);e=p.ln(t);for(var s=0;s<100;++s){if(i=e.neg().exp(),r=e.sub(t.mul(i)),a=e.sub(r.div(e.add(1).sub(e.add(2).mul(r).div(p.mul(2,e).add(2))))),p.abs(a.sub(e)).lt(p.abs(a).mul(n)))return a;e=a}throw Error("Iteration failed to converge: ".concat(t.toString()))}var p=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)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),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)),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=t,r=e.fromStringCache.get(i);if(void 0!==r)return this.fromDecimal(r);var a=(t=t.replace(",","")).split("^^^");if(2===a.length){var n=parseFloat(a[0]),s=parseFloat(a[1]),u=a[1].split(";"),o=1;if(2===u.length&&(o=parseFloat(u[1]),isFinite(o)||(o=1)),isFinite(n)&&isFinite(s)){var l=e.pentate(n,s,o);return this.sign=l.sign,this.layer=l.layer,this.mag=l.mag,e.fromStringCache.maxSize>=1&&e.fromStringCache.set(i,e.fromDecimal(this)),this}}var g=t.split("^^");if(2===g.length){var f=parseFloat(g[0]),y=parseFloat(g[1]),v=g[1].split(";"),d=1;if(2===v.length&&(d=parseFloat(v[1]),isFinite(d)||(d=1)),isFinite(f)&&isFinite(y)){var p=e.tetrate(f,y,d);return this.sign=p.sign,this.layer=p.layer,this.mag=p.mag,e.fromStringCache.maxSize>=1&&e.fromStringCache.set(i,e.fromDecimal(this)),this}}var k,b,N=t.split("^");if(2===N.length){var M=parseFloat(N[0]),w=parseFloat(N[1]);if(isFinite(M)&&isFinite(w)){var _=e.pow(M,w);return this.sign=_.sign,this.layer=_.layer,this.mag=_.mag,e.fromStringCache.maxSize>=1&&e.fromStringCache.set(i,e.fromDecimal(this)),this}}var q=(t=t.trim().toLowerCase()).split("pt");if(2===q.length){k=10,b=parseFloat(q[0]),q[1]=q[1].replace("(",""),q[1]=q[1].replace(")","");var F=parseFloat(q[1]);if(isFinite(F)||(F=1),isFinite(k)&&isFinite(b)){var S=e.tetrate(k,b,F);return this.sign=S.sign,this.layer=S.layer,this.mag=S.mag,e.fromStringCache.maxSize>=1&&e.fromStringCache.set(i,e.fromDecimal(this)),this}}if(2===(q=t.split("p")).length){k=10,b=parseFloat(q[0]),q[1]=q[1].replace("(",""),q[1]=q[1].replace(")","");var x=parseFloat(q[1]);if(isFinite(x)||(x=1),isFinite(k)&&isFinite(b)){var I=e.tetrate(k,b,x);return this.sign=I.sign,this.layer=I.layer,this.mag=I.mag,e.fromStringCache.maxSize>=1&&e.fromStringCache.set(i,e.fromDecimal(this)),this}}if(2===(q=t.split("f")).length){k=10,q[0]=q[0].replace("(",""),q[0]=q[0].replace(")","");var E=parseFloat(q[0]);if(q[1]=q[1].replace("(",""),q[1]=q[1].replace(")",""),b=parseFloat(q[1]),isFinite(E)||(E=1),isFinite(k)&&isFinite(b)){var C=e.tetrate(k,b,E);return this.sign=C.sign,this.layer=C.layer,this.mag=C.mag,e.fromStringCache.maxSize>=1&&e.fromStringCache.set(i,e.fromDecimal(this)),this}}var O=t.split("e"),z=O.length-1;if(0===z){var T=parseFloat(t);if(isFinite(T))return this.fromNumber(T),e.fromStringCache.size>=1&&e.fromStringCache.set(i,e.fromDecimal(this)),this}else if(1===z){var D=parseFloat(t);if(isFinite(D)&&0!==D)return this.fromNumber(D),e.fromStringCache.maxSize>=1&&e.fromStringCache.set(i,e.fromDecimal(this)),this}var Z=t.split("e^");if(2===Z.length){this.sign=1,"-"==Z[0].charAt(0)&&(this.sign=-1);for(var P="",V=0;V=43&&A<=57||101===A))return this.layer=parseFloat(P),this.mag=parseFloat(Z[1].substr(V+1)),this.normalize(),e.fromStringCache.maxSize>=1&&e.fromStringCache.set(i,e.fromDecimal(this)),this;P+=Z[1].charAt(V)}}if(z<1)return this.sign=0,this.layer=0,this.mag=0,e.fromStringCache.maxSize>=1&&e.fromStringCache.set(i,e.fromDecimal(this)),this;var Y=parseFloat(O[0]);if(0===Y)return this.sign=0,this.layer=0,this.mag=0,e.fromStringCache.maxSize>=1&&e.fromStringCache.set(i,e.fromDecimal(this)),this;var G=parseFloat(O[O.length-1]);if(z>=2){var L=parseFloat(O[O.length-2]);isFinite(L)&&(G*=Math.sign(L),G+=c(L))}if(isFinite(Y))if(1===z)this.sign=Math.sign(Y),this.layer=1,this.mag=G+Math.log10(Math.abs(Y));else{if(this.sign=Math.sign(Y),this.layer=z,2===z){var j=e.mul(m(1,2,G),h(Y));return this.sign=j.sign,this.layer=j.layer,this.mag=j.mag,e.fromStringCache.maxSize>=1&&e.fromStringCache.set(i,e.fromDecimal(this)),this}this.mag=G}else this.sign="-"===O[0]?-1:1,this.layer=z,this.mag=G;return this.normalize(),e.fromStringCache.maxSize>=1&&e.fromStringCache.set(i,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 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?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?e.dZero:0===this.layer?m(this.sign,0,Math.floor(this.mag)):this}},{key:"ceil",value:function(){return this.mag<0?e.dZero: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,a=h(t);if(!Number.isFinite(this.layer))return this;if(!Number.isFinite(a.layer))return a;if(0===this.sign)return a;if(0===a.sign)return 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(e.cmpabs(this,a)>0?(i=this,r=a):(i=a,r=this),0===i.layer&&0===r.layer)return e.fromNumber(i.sign*i.mag+r.sign*r.mag);var n=i.layer*Math.sign(i.mag),s=r.layer*Math.sign(r.mag);if(n-s>=2)return i;if(0===n&&-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===n&&0===s){if(Math.abs(i.mag-Math.log10(r.mag))>17)return i;var l=Math.pow(10,i.mag-Math.log10(r.mag)),f=r.sign+i.sign*l;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(h(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,a=h(t);if(!Number.isFinite(this.layer))return this;if(!Number.isFinite(a.layer))return 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)?(i=this,r=a):(i=a,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 n=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,n.layer+1,n.sign*n.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=h(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=h(t).abs();if(i.eq(e.dZero))return e.dZero;var r=this.toNumber(),a=i.toNumber();return isFinite(r)&&isFinite(a)&&0!=r&&0!=a?new e(r%a):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=h(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=h(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=h(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,a=i.mag;return this.layer>i.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?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=h(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=h(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 a=i.absLog10().mul(r).pow10();return-1===this.sign?Math.abs(r.toNumber()%2)%2==1?a.neg():Math.abs(r.toNumber()%2)%2==0?a:e.dNaN:a}},{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 h(t).pow(this)}},{key:"root",value:function(t){var e=h(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,a=t;return i+=1/(12*a),i+=1/(360*(a*=r)),i+=1/(1260*(a*=r)),i+=1/(1680*(a*=r)),i+=1/(1188*(a*=r)),i+=691/(360360*(a*=r)),i+=7/(1092*(a*=r)),i+=3617/(122400*(a*=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,a=t,n=12*a,s=1/n,u=(i-=t)+s;if(u===i)return e.exp(i);if((u=(i=u)-(s=1/(n=360*(a*=r))))===i)return e.exp(i);i=u;var o=1/(n=1260*(a*=r));return i+=o,i-=o=1/(n=1680*(a*=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 a=this.toNumber();if(a<=1.444667861009766&&a>=.06598803584531254){if(a>1.444667861009099)return e.fromNumber(Math.E);var n=e.ln(this).neg();return n.lambertw().div(n)}return a>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=h(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 l=0;l1e4){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=h(t);var a=e.fromDecimal(this),n=i,s=n-(i=Math.trunc(i));if(a.layer-t.layer>3){var u=Math.min(i,a.layer-t.layer-3);i-=u,a.layer-=u}for(var o=0;o1e4)return a}return s>0&&s<1&&(a=t.eq(10)?a.layeradd10(-s,r):a.layeradd(-s,t,r)),a}},{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],a=.001,n=!1,s=!1,u=this.slog_internal(t,r).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 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=h(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,a=e.fromDecimal(this);if(a.layer-t.layer>3){var n=a.layer-t.layer-3;r+=n,a.layer-=n}for(var s=0;s<100;++s)if(a.lt(e.dZero))a=e.pow(t,a),r-=1;else{if(a.lte(e.dOne))return i?e.fromNumber(r+a.toNumber()-1):e.fromNumber(r+e.slog_critical(t.toNumber(),a.toNumber()));r+=1,a=e.log(a,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 a=Math.trunc(t);t-=a,r.layer+=a}if(t<=-1){var n=Math.trunc(t);if(t-=n,r.layer+=n,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],a=this.slog(i).toNumber(),n=a+t;return n>=0?e.tetrate(i,n,e.dOne,r):Number.isFinite(n)?n>=-1?e.log(e.tetrate(i,n+1,e.dOne,r),i):e.log(e.log(e.tetrate(i,n+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(){if(1==this.sign&&this.layer>=3)return g(this.sign,this.layer-1,this.mag);var t=this.ln();return t.div(t.lambertw())}},{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(2==t)try{return this.ssqrt()}catch(t){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 a=e.dZero,n=r.layer,s=r.iteratedlog(10,n,!0),u=s,o=s.div(2),l=!0;l;)o=a.add(s).div(2),e.iteratedexp(10,n,o,!0).tetrate(t,1,!0).gt(this)?s=o:a=o,o.eq(u)?l=!1:u=o;return e.iteratedexp(10,n,o,!0)}for(var h=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),p=y.pow10().recip(),k=e.dZero,b=p,N=p,M=Math.ceil(t)%2==0,w=0,_=m(1,10,1),q=!1,F=e.dZero,S=!1;h<4;){if(2==h){if(M)break;c=m(1,10,1),y=g,h=3,d=m(1,10,1),_=m(1,10,1)}for(q=!1;y.neq(c);){if(F=y,y.pow10().recip().tetrate(t,1,!0).eq(1)&&y.pow10().recip().lt(.4))p=y.pow10().recip(),b=y.pow10().recip(),N=y.pow10().recip(),k=e.dZero,w=-1,3==h&&(_=y);else if(y.pow10().recip().tetrate(t,1,!0).eq(y.pow10().recip())&&!M&&y.pow10().recip().lt(.4))p=y.pow10().recip(),b=y.pow10().recip(),N=y.pow10().recip(),k=e.dZero,w=0;else if(y.pow10().recip().tetrate(t,1,!0).eq(y.pow10().recip().mul(2).tetrate(t,1,!0)))p=y.pow10().recip(),b=e.dZero,N=p.mul(2),k=p,w=M?-1:0;else{for(v=y.mul(12e-17),p=y.pow10().recip(),b=y.add(v).pow10().recip(),k=p.sub(b),N=p.add(k);b.tetrate(t,1,!0).eq(p.tetrate(t,1,!0))||N.tetrate(t,1,!0).eq(p.tetrate(t,1,!0))||b.gte(p)||N.lte(p);)v=v.mul(2),b=y.add(v).pow10().recip(),k=p.sub(b),N=p.add(k);if((1==h&&N.tetrate(t,1,!0).gt(p.tetrate(t,1,!0))&&b.tetrate(t,1,!0).gt(p.tetrate(t,1,!0))||3==h&&N.tetrate(t,1,!0).lt(p.tetrate(t,1,!0))&&b.tetrate(t,1,!0).lt(p.tetrate(t,1,!0)))&&(_=y),N.tetrate(t,1,!0).lt(p.tetrate(t,1,!0)))w=-1;else if(M)w=1;else if(3==h&&y.gt_tolerance(g,1e-8))w=0;else{for(;b.tetrate(t,1,!0).eq_tolerance(p.tetrate(t,1,!0),1e-8)||N.tetrate(t,1,!0).eq_tolerance(p.tetrate(t,1,!0),1e-8)||b.gte(p)||N.lte(p);)v=v.mul(2),b=y.add(v).pow10().recip(),k=p.sub(b),N=p.add(k);w=N.tetrate(t,1,!0).sub(p.tetrate(t,1,!0)).lt(p.tetrate(t,1,!0).sub(b.tetrate(t,1,!0)))?0:1}}if(-1==w&&(S=!0),1==h&&1==w||3==h&&0!=w)if(c.eq(m(1,10,1)))y=y.mul(2);else{var x=!1;if(q&&(1==w&&1==h||-1==w&&3==h)&&(x=!0),y=y.add(c).div(2),x)break}else if(c.eq(m(1,10,1)))c=y,y=y.div(2);else{var I=!1;if(q&&(1==w&&1==h||-1==w&&3==h)&&(I=!0),c=c.sub(d),y=y.sub(d),I)break}if(c.sub(y).div(2).abs().gt(d.mul(1.5))&&(q=!0),d=c.sub(y).div(2).abs(),y.gt("1e18"))break;if(y.eq(F))break}if(y.gt("1e18"))break;if(!S)break;if(_==m(1,10,1))break;1==h?g=_:3==h&&(f=_),h++}c=g;for(var E=y=m(1,1,-18),C=e.dZero,O=!0;O;)if(C=c.eq(m(1,10,1))?y.mul(2):c.add(y).div(2),e.pow(10,C).recip().tetrate(t,1,!0).gt(this)?y=C:c=C,C.eq(E)?O=!1:E=C,y.gt("1e18"))return e.dNaN;if(C.eq_tolerance(g,1e-15)){if(f.eq(m(1,10,1)))return e.dNaN;for(c=m(1,10,1),E=y=f,C=e.dZero,O=!0;O;)if(C=c.eq(m(1,10,1))?y.mul(2):c.add(y).div(2),e.pow(10,C).recip().tetrate(t,1,!0).gt(this)?y=C:c=C,C.eq(E)?O=!1:E=C,y.gt("1e18"))return e.dNaN;return C.pow10().recip()}return C.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=h(i);var a=t,n=a-(t=Math.trunc(t));0!==n&&(i.eq(e.dOne)?(++t,i=e.fromNumber(n)):i=this.eq(10)?i.layeradd10(n,r):i.layeradd(n,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){return(new e).fromString(t)}},{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 h(t).abs()}},{key:"neg",value:function(t){return h(t).neg()}},{key:"negate",value:function(t){return h(t).neg()}},{key:"negated",value:function(t){return h(t).neg()}},{key:"sign",value:function(t){return h(t).sign}},{key:"sgn",value:function(t){return h(t).sign}},{key:"round",value:function(t){return h(t).round()}},{key:"floor",value:function(t){return h(t).floor()}},{key:"ceil",value:function(t){return h(t).ceil()}},{key:"trunc",value:function(t){return h(t).trunc()}},{key:"add",value:function(t,e){return h(t).add(e)}},{key:"plus",value:function(t,e){return h(t).add(e)}},{key:"sub",value:function(t,e){return h(t).sub(e)}},{key:"subtract",value:function(t,e){return h(t).sub(e)}},{key:"minus",value:function(t,e){return h(t).sub(e)}},{key:"mul",value:function(t,e){return h(t).mul(e)}},{key:"multiply",value:function(t,e){return h(t).mul(e)}},{key:"times",value:function(t,e){return h(t).mul(e)}},{key:"div",value:function(t,e){return h(t).div(e)}},{key:"divide",value:function(t,e){return h(t).div(e)}},{key:"recip",value:function(t){return h(t).recip()}},{key:"reciprocal",value:function(t){return h(t).recip()}},{key:"reciprocate",value:function(t){return h(t).reciprocate()}},{key:"mod",value:function(t,e){return h(t).mod(e)}},{key:"modulo",value:function(t,e){return h(t).modulo(e)}},{key:"modular",value:function(t,e){return h(t).modular(e)}},{key:"cmp",value:function(t,e){return h(t).cmp(e)}},{key:"cmpabs",value:function(t,e){return h(t).cmpabs(e)}},{key:"compare",value:function(t,e){return h(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=h(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=h(t),isFinite(t.sign)&&isFinite(t.layer)&&isFinite(t.mag)}))},{key:"eq",value:function(t,e){return h(t).eq(e)}},{key:"equals",value:function(t,e){return h(t).eq(e)}},{key:"neq",value:function(t,e){return h(t).neq(e)}},{key:"notEquals",value:function(t,e){return h(t).notEquals(e)}},{key:"lt",value:function(t,e){return h(t).lt(e)}},{key:"lte",value:function(t,e){return h(t).lte(e)}},{key:"gt",value:function(t,e){return h(t).gt(e)}},{key:"gte",value:function(t,e){return h(t).gte(e)}},{key:"max",value:function(t,e){return h(t).max(e)}},{key:"min",value:function(t,e){return h(t).min(e)}},{key:"minabs",value:function(t,e){return h(t).minabs(e)}},{key:"maxabs",value:function(t,e){return h(t).maxabs(e)}},{key:"clamp",value:function(t,e,i){return h(t).clamp(e,i)}},{key:"clampMin",value:function(t,e){return h(t).clampMin(e)}},{key:"clampMax",value:function(t,e){return h(t).clampMax(e)}},{key:"cmp_tolerance",value:function(t,e,i){return h(t).cmp_tolerance(e,i)}},{key:"compare_tolerance",value:function(t,e,i){return h(t).cmp_tolerance(e,i)}},{key:"eq_tolerance",value:function(t,e,i){return h(t).eq_tolerance(e,i)}},{key:"equals_tolerance",value:function(t,e,i){return h(t).eq_tolerance(e,i)}},{key:"neq_tolerance",value:function(t,e,i){return h(t).neq_tolerance(e,i)}},{key:"notEquals_tolerance",value:function(t,e,i){return h(t).notEquals_tolerance(e,i)}},{key:"lt_tolerance",value:function(t,e,i){return h(t).lt_tolerance(e,i)}},{key:"lte_tolerance",value:function(t,e,i){return h(t).lte_tolerance(e,i)}},{key:"gt_tolerance",value:function(t,e,i){return h(t).gt_tolerance(e,i)}},{key:"gte_tolerance",value:function(t,e,i){return h(t).gte_tolerance(e,i)}},{key:"pLog10",value:function(t){return h(t).pLog10()}},{key:"absLog10",value:function(t){return h(t).absLog10()}},{key:"log10",value:function(t){return h(t).log10()}},{key:"log",value:function(t,e){return h(t).log(e)}},{key:"log2",value:function(t){return h(t).log2()}},{key:"ln",value:function(t){return h(t).ln()}},{key:"logarithm",value:function(t,e){return h(t).logarithm(e)}},{key:"pow",value:function(t,e){return h(t).pow(e)}},{key:"pow10",value:function(t){return h(t).pow10()}},{key:"root",value:function(t,e){return h(t).root(e)}},{key:"factorial",value:function(t,e){return h(t).factorial()}},{key:"gamma",value:function(t,e){return h(t).gamma()}},{key:"lngamma",value:function(t,e){return h(t).lngamma()}},{key:"exp",value:function(t){return h(t).exp()}},{key:"sqr",value:function(t){return h(t).sqr()}},{key:"sqrt",value:function(t){return h(t).sqrt()}},{key:"cube",value:function(t){return h(t).cube()}},{key:"cbrt",value:function(t){return h(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 h(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 h(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 h(t).iteratedlog(e,i,r)}},{key:"layeradd10",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]&&arguments[2];return h(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 h(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 h(t).slog(e,100,i)}},{key:"lambertw",value:function(t){return h(t).lambertw()}},{key:"ssqrt",value:function(t){return h(t).ssqrt()}},{key:"linear_sroot",value:function(t,e){return h(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 h(t).pentate(e,i,r)}},{key:"affordGeometricSeries",value:function(t,e,i,r){return this.affordGeometricSeries_core(h(t),h(e),h(i),r)}},{key:"sumGeometricSeries",value:function(t,e,i,r){return this.sumGeometricSeries_core(t,h(e),h(i),r)}},{key:"affordArithmeticSeries",value:function(t,e,i,r){return this.affordArithmeticSeries_core(h(t),h(e),h(i),h(r))}},{key:"sumArithmeticSeries",value:function(t,e,i,r){return this.sumArithmeticSeries_core(h(t),h(e),h(i),h(r))}},{key:"efficiencyOfPurchase",value:function(t,e,i){return this.efficiencyOfPurchase_core(h(t),h(e),h(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 a=Math.pow(10,r);return Math.random()>.9&&(a=Math.trunc(a)),m(e,i,a)}},{key:"affordGeometricSeries_core",value:function(t,i,r,a){var n=i.mul(r.pow(a));return e.floor(t.div(n).mul(r.sub(1)).add(1).log10().div(r.log10()))}},{key:"sumGeometricSeries_core",value:function(t,i,r,a){return i.mul(r.pow(a)).mul(e.sub(1,r.pow(t))).div(e.sub(1,r))}},{key:"affordArithmeticSeries_core",value:function(t,e,i,r){var a=e.add(r.mul(i)).sub(i.div(2)),n=a.pow(2);return a.neg().add(n.add(i.mul(t).mul(2)).sqrt()).div(i).floor()}},{key:"sumArithmeticSeries_core",value:function(t,e,i,r){var a=e.add(r.mul(i));return t.div(2).mul(a.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,l)}},{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,a=0,n=0;nt){var s=(t-u[n])/(u[n+1]-u[n]);r=i[n][Math.floor(e)]*(1-s)+i[n+1][Math.floor(e)]*s,a=i[n][Math.ceil(e)]*(1-s)+i[n+1][Math.ceil(e)]*s;break}}var o=e-Math.floor(e);return r<=0||a<=0?r*(1-o)+a*o:Math.pow(t,Math.log(r)/Math.log(t)*(1-o)+Math.log(a)/Math.log(t)*o)}}]),e}();return p.dZero=g(0,0,0),p.dOne=g(1,0,1),p.dNegOne=g(-1,0,1),p.dTwo=g(1,0,2),p.dTen=g(1,0,10),p.dNaN=g(Number.NaN,Number.NaN,Number.NaN),p.dInf=g(1,Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY),p.dNegInf=g(-1,Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY),p.dNumberMax=m(1,0,Number.MAX_VALUE),p.dNumberMin=m(1,0,Number.MIN_VALUE),p.fromStringCache=new r(1023),h=p.fromValue_noAlloc,m=p.fromComponents,g=p.fromComponents_noNormalize,p.fromMantissaExponent,p.fromMantissaExponent_noNormalize,p})); diff --git a/index.d.ts b/index.d.ts index 3a00722..f2bb97a 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,7 +1,7 @@ -export declare type CompareResult = -1 | 0 | 1; -export declare type DecimalSource = Decimal | number | string; +export type CompareResult = -1 | 0 | 1; +export type DecimalSource = Decimal | number | string; /** - * The Decimal's value is simply mantissa * 10^exponent. + * The value of the Decimal is sign * 10^10^10...^mag, with (layer) 10s. If the layer is not 0, then negative mag means it's the reciprocal of the corresponding number with positive mag. */ export default class Decimal { static readonly dZero: Decimal; @@ -70,6 +70,9 @@ export default class Decimal { static recip(value: DecimalSource): Decimal; static reciprocal(value: DecimalSource): Decimal; static reciprocate(value: DecimalSource): Decimal; + static mod(value: DecimalSource, other: DecimalSource): Decimal; + static modulo(value: DecimalSource, other: DecimalSource): Decimal; + static modular(value: DecimalSource, other: DecimalSource): Decimal; static cmp(value: DecimalSource, other: DecimalSource): CompareResult; static cmpabs(value: DecimalSource, other: DecimalSource): CompareResult; static compare(value: DecimalSource, other: DecimalSource): CompareResult; @@ -118,15 +121,16 @@ export default class Decimal { static sqrt(value: DecimalSource): Decimal; static cube(value: DecimalSource): Decimal; static cbrt(value: DecimalSource): Decimal; - static tetrate(value: DecimalSource, height?: number, payload?: DecimalSource): Decimal; - static iteratedexp(value: DecimalSource, height?: number, payload?: Decimal): Decimal; - static iteratedlog(value: DecimalSource, base?: DecimalSource, times?: number): Decimal; - static layeradd10(value: DecimalSource, diff: DecimalSource): Decimal; - static layeradd(value: DecimalSource, diff: number, base?: number): Decimal; - static slog(value: DecimalSource, base?: number): Decimal; + static tetrate(value: DecimalSource, height?: number, payload?: DecimalSource, linear?: boolean): Decimal; + static iteratedexp(value: DecimalSource, height?: number, payload?: Decimal, linear?: boolean): Decimal; + static iteratedlog(value: DecimalSource, base?: DecimalSource, times?: number, linear?: boolean): Decimal; + static layeradd10(value: DecimalSource, diff: DecimalSource, linear?: boolean): Decimal; + static layeradd(value: DecimalSource, diff: number, base?: number, linear?: boolean): Decimal; + static slog(value: DecimalSource, base?: number, linear?: boolean): Decimal; static lambertw(value: DecimalSource): Decimal; static ssqrt(value: DecimalSource): Decimal; - static pentate(value: DecimalSource, height?: number, payload?: DecimalSource): Decimal; + static linear_sroot(value: DecimalSource, height: number): Decimal; + static pentate(value: DecimalSource, height?: number, payload?: DecimalSource, linear?: boolean): Decimal; /** * If you're willing to spend 'resourcesAvailable' and want to buy something * with exponentially increasing cost each purchase (start at priceStart, @@ -207,6 +211,9 @@ export default class Decimal { recip(): Decimal; reciprocal(): Decimal; reciprocate(): Decimal; + mod(value: DecimalSource): Decimal; + modulo(value: DecimalSource): Decimal; + modular(value: DecimalSource): Decimal; /** * -1 for less than value, 0 for equals value, 1 for greater than value */ @@ -264,19 +271,20 @@ export default class Decimal { sqrt(): Decimal; cube(): Decimal; cbrt(): Decimal; - tetrate(height?: number, payload?: DecimalSource): Decimal; - iteratedexp(height?: number, payload?: Decimal): Decimal; - iteratedlog(base?: DecimalSource, times?: number): Decimal; - slog(base?: DecimalSource, iterations?: number): Decimal; - slog_internal(base?: DecimalSource): Decimal; + tetrate(height?: number, payload?: DecimalSource, linear?: boolean): Decimal; + iteratedexp(height?: number, payload?: Decimal, linear?: boolean): Decimal; + iteratedlog(base?: DecimalSource, times?: number, linear?: boolean): Decimal; + slog(base?: DecimalSource, iterations?: number, linear?: boolean): Decimal; + slog_internal(base?: DecimalSource, linear?: boolean): Decimal; static slog_critical(base: number, height: number): number; static tetrate_critical(base: number, height: number): number; - static critical_section(base: number, height: number, grid: number[][]): number; - layeradd10(diff: DecimalSource): Decimal; - layeradd(diff: number, base: DecimalSource): Decimal; + static critical_section(base: number, height: number, grid: number[][], linear?: boolean): number; + layeradd10(diff: DecimalSource, linear?: boolean): Decimal; + layeradd(diff: number, base: DecimalSource, linear?: boolean): Decimal; lambertw(): Decimal; ssqrt(): Decimal; - pentate(height?: number, payload?: DecimalSource): Decimal; + linear_sroot(degree: number): Decimal; + pentate(height?: number, payload?: DecimalSource, linear?: boolean): Decimal; sin(): this | Decimal; cos(): Decimal; tan(): this | Decimal; diff --git a/src/index.ts b/src/index.ts index 5a867c2..f4c5d23 100644 --- a/src/index.ts +++ b/src/index.ts @@ -338,7 +338,7 @@ function d_lambertw(z: Decimal, tol = 1e-10): Decimal { export type DecimalSource = Decimal | number | string; /** - * The Decimal's value is simply mantissa * 10^exponent. + * The value of the Decimal is sign * 10^10^10...^mag, with (layer) 10s. If the layer is not 0, then negative mag means it's the reciprocal of the corresponding number with positive mag. */ export default class Decimal { public static readonly dZero = FC_NN(0, 0, 0); @@ -601,6 +601,18 @@ export default class Decimal { return D(value).reciprocate(); } + public static mod(value: DecimalSource, other: DecimalSource): Decimal { + return D(value).mod(other); + } + + public static modulo(value: DecimalSource, other: DecimalSource): Decimal { + return D(value).modulo(other); + } + + public static modular(value: DecimalSource, other: DecimalSource): Decimal { + return D(value).modular(other); + } + public static cmp(value: DecimalSource, other: DecimalSource): CompareResult { return D(value).cmp(other); } @@ -838,29 +850,30 @@ export default class Decimal { public static tetrate( value: DecimalSource, height = 2, - payload: DecimalSource = FC_NN(1, 0, 1) + payload: DecimalSource = FC_NN(1, 0, 1), + linear = false ): Decimal { - return D(value).tetrate(height, payload); + return D(value).tetrate(height, payload, linear); } - public static iteratedexp(value: DecimalSource, height = 2, payload = FC_NN(1, 0, 1)): Decimal { - return D(value).iteratedexp(height, payload); + public static iteratedexp(value: DecimalSource, height = 2, payload = FC_NN(1, 0, 1), linear = false): Decimal { + return D(value).iteratedexp(height, payload, linear); } - public static iteratedlog(value: DecimalSource, base: DecimalSource = 10, times = 1): Decimal { - return D(value).iteratedlog(base, times); + public static iteratedlog(value: DecimalSource, base: DecimalSource = 10, times = 1, linear = false): Decimal { + return D(value).iteratedlog(base, times, linear); } - public static layeradd10(value: DecimalSource, diff: DecimalSource): Decimal { - return D(value).layeradd10(diff); + public static layeradd10(value: DecimalSource, diff: DecimalSource, linear = false): Decimal { + return D(value).layeradd10(diff, linear); } - public static layeradd(value: DecimalSource, diff: number, base = 10): Decimal { - return D(value).layeradd(diff, base); + public static layeradd(value: DecimalSource, diff: number, base = 10, linear = false): Decimal { + return D(value).layeradd(diff, base, linear); } - public static slog(value: DecimalSource, base = 10): Decimal { - return D(value).slog(base); + public static slog(value: DecimalSource, base = 10, linear = false): Decimal { + return D(value).slog(base, 100, linear); } public static lambertw(value: DecimalSource): Decimal { @@ -871,12 +884,17 @@ export default class Decimal { return D(value).ssqrt(); } + public static linear_sroot(value: DecimalSource, height: number): Decimal { + return D(value).linear_sroot(height); + } + public static pentate( value: DecimalSource, height = 2, - payload: DecimalSource = FC_NN(1, 0, 1) + payload: DecimalSource = FC_NN(1, 0, 1), + linear = false ): Decimal { - return D(value).pentate(height, payload); + return D(value).pentate(height, payload, linear); } /** @@ -1302,6 +1320,31 @@ export default class Decimal { } } + //handle XFY format + ptparts = value.split("f"); + if (ptparts.length === 2) { + base = 10; + ptparts[0] = ptparts[0].replace("(", ""); + ptparts[0] = ptparts[0].replace(")", ""); + let payload = parseFloat(ptparts[0]); + ptparts[1] = ptparts[1].replace("(", ""); + ptparts[1] = ptparts[1].replace(")", ""); + height = parseFloat(ptparts[1]); + if (!isFinite(payload)) { + payload = 1; + } + if (isFinite(base) && isFinite(height)) { + const result = Decimal.tetrate(base, height, payload); + this.sign = result.sign; + this.layer = result.layer; + this.mag = result.mag; + if (Decimal.fromStringCache.maxSize >= 1) { + Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); + } + return this; + } + } + const parts = value.split("e"); const ecount = parts.length - 1; @@ -1841,6 +1884,38 @@ export default class Decimal { return this.recip(); } + //Taken from OmegaNum.js, with a couple touch-ups + //"Truncated division" modulo, like JavaScript's % + public mod(value: DecimalSource): Decimal { + const decimal = D(value).abs(); + + if (decimal.eq(Decimal.dZero)) return Decimal.dZero; + 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 + if (isFinite(num_this) && isFinite(num_decimal) && num_this != 0 && num_decimal != 0) { + return new Decimal(num_this % num_decimal); + } + if (this.sub(decimal).eq(this)) { + //decimal is too small to register to this + return Decimal.dZero; + } + if (decimal.sub(this).eq(decimal)) { + //this is too small to register to decimal + return this; + } + if (this.sign == -1) return this.abs().mod(decimal).neg(); + return this.sub(this.div(decimal).floor().mul(decimal)); + } + + public modulo(value: DecimalSource) : Decimal { + return this.mod(value); + } + + public modular(value: DecimalSource) : Decimal { + return this.mod(value); + } + /** * -1 for less than value, 0 for equals value, 1 for greater than value */ @@ -2289,7 +2364,7 @@ export default class Decimal { //Tetration/tetrate: The result of exponentiating 'this' to 'this' 'height' times in a row. https://en.wikipedia.org/wiki/Tetration //If payload != 1, then this is 'iterated exponentiation', the result of exping (payload) to base (this) (height) times. https://andydude.github.io/tetration/archives/tetration2/ident.html //Works with negative and positive real heights. - public tetrate(height = 2, payload: DecimalSource = FC_NN(1, 0, 1)): Decimal { + public tetrate(height = 2, payload: DecimalSource = FC_NN(1, 0, 1), linear = false): Decimal { //x^^1 == x if (height === 1) { return Decimal.pow(this, payload); @@ -2340,7 +2415,7 @@ export default class Decimal { } if (height < 0) { - return Decimal.iteratedlog(payload, this, -height); + return Decimal.iteratedlog(payload, this, -height, linear); } payload = D(payload); @@ -2348,7 +2423,7 @@ export default class Decimal { height = Math.trunc(height); const fracheight = oldheight - height; - if (this.gt(Decimal.dZero) && this.lte(1.44466786100976613366)) { + 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) { @@ -2359,9 +2434,14 @@ export default class Decimal { return payload; } } - if (fracheight != 0) { + if (fracheight != 0 || oldheight > 10000) { const next_payload = this.pow(payload); - return payload.mul(1 - fracheight).add(next_payload.mul(fracheight)); + 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)); + } } return payload; } @@ -2369,8 +2449,9 @@ export default class Decimal { if (fracheight !== 0) { if (payload.eq(Decimal.dOne)) { + //If (linear), use linear approximation even for bases <= 10 //TODO: for bases above 10, revert to old linear approximation until I can think of something better - if (this.gt(10)) { + if (this.gt(10) || linear) { payload = this.pow(fracheight); } else { payload = Decimal.fromNumber(Decimal.tetrate_critical(this.toNumber(), fracheight)); @@ -2382,9 +2463,9 @@ export default class Decimal { } } else { if (this.eq(10)) { - payload = payload.layeradd10(fracheight); + payload = payload.layeradd10(fracheight, linear); } else { - payload = payload.layeradd(fracheight, this); + payload = payload.layeradd(fracheight, this, linear); } } } @@ -2408,15 +2489,15 @@ export default class Decimal { } //iteratedexp/iterated exponentiation: - all cases handled in tetrate, so just call it - public iteratedexp(height = 2, payload = FC_NN(1, 0, 1)): Decimal { - return this.tetrate(height, payload); + public iteratedexp(height = 2, payload = FC_NN(1, 0, 1), linear = false): Decimal { + return this.tetrate(height, payload, linear); } //iterated log/repeated log: The result of applying log(base) 'times' times in a row. Approximately equal to subtracting (times) from the number's slog representation. Equivalent to tetrating to a negative height. //Works with negative and positive real heights. - public iteratedlog(base: DecimalSource = 10, times = 1): Decimal { + public iteratedlog(base: DecimalSource = 10, times = 1, linear = false): Decimal { if (times < 0) { - return Decimal.tetrate(base, -times, this); + return Decimal.tetrate(base, -times, this, linear); } base = D(base); @@ -2445,9 +2526,9 @@ export default class Decimal { //handle fractional part if (fraction > 0 && fraction < 1) { if (base.eq(10)) { - result = result.layeradd10(-fraction); + result = result.layeradd10(-fraction, linear); } else { - result = result.layeradd(-fraction, base); + result = result.layeradd(-fraction, base, linear); } } @@ -2457,14 +2538,14 @@ export default class Decimal { //Super-logarithm, one of tetration's inverses, tells you what size power tower you'd have to tetrate base to to get number. By definition, will never be higher than 1.8e308 in break_eternity.js, since a power tower 1.8e308 numbers tall is the largest representable number. // https://en.wikipedia.org/wiki/Super-logarithm // NEW: Accept a number of iterations, and use binary search to, after making an initial guess, hone in on the true value, assuming tetration as the ground truth. - public slog(base: DecimalSource = 10, iterations = 100): Decimal { + public slog(base: DecimalSource = 10, iterations = 100, linear = false): Decimal { let step_size = 0.001; let has_changed_directions_once = false; let previously_rose = false; - let result = this.slog_internal(base).toNumber(); + let result = this.slog_internal(base, linear).toNumber(); for (var i = 1; i < iterations; ++i) { - let new_decimal = new Decimal(base).tetrate(result); + let new_decimal = new Decimal(base).tetrate(result, Decimal.dOne, linear); let currently_rose = new_decimal.gt(this); if (i > 1) { @@ -2489,7 +2570,7 @@ export default class Decimal { return Decimal.fromNumber(result); } - public slog_internal(base: DecimalSource = 10): Decimal { + public slog_internal(base: DecimalSource = 10, linear = false): Decimal { base = D(base); //special cases: @@ -2532,7 +2613,8 @@ export default class Decimal { copy = Decimal.pow(base, copy); result -= 1; } else if (copy.lte(Decimal.dOne)) { - return Decimal.fromNumber(result + Decimal.slog_critical(base.toNumber(), copy.toNumber())); + if (linear) return Decimal.fromNumber(result + copy.toNumber() - 1); + else return Decimal.fromNumber(result + Decimal.slog_critical(base.toNumber(), copy.toNumber())); } else { result += 1; copy = Decimal.log(copy, base); @@ -2554,7 +2636,7 @@ export default class Decimal { return Decimal.critical_section(base, height, critical_tetr_values); } - public static critical_section(base: number, height: number, grid: number[][]): number { + public static critical_section(base: number, height: number, grid: number[][], linear = false): number { //this part is simple at least, since it's just 0.1 to 0.9 height *= 10; if (height < 0) { @@ -2609,7 +2691,7 @@ export default class Decimal { //Function for adding/removing layers from a Decimal, even fractional layers (e.g. its slog10 representation). //Moved this over to use the same critical section as tetrate/slog. - public layeradd10(diff: DecimalSource): Decimal { + public layeradd10(diff: DecimalSource, linear = false): Decimal { diff = Decimal.fromValue_noAlloc(diff).toNumber(); const result = Decimal.fromDecimal(this); if (diff >= 1) { @@ -2669,24 +2751,24 @@ export default class Decimal { //layeradd10: like adding 'diff' to the number's slog(base) representation. Very similar to tetrate base 10 and iterated log base 10. Also equivalent to adding a fractional amount to the number's layer in its break_eternity.js representation. if (diff !== 0) { - return result.layeradd(diff, 10); //safe, only calls positive height 1 payload tetration, slog and log + return result.layeradd(diff, 10, linear); //safe, only calls positive height 1 payload tetration, slog and log } return result; } //layeradd: like adding 'diff' to the number's slog(base) representation. Very similar to tetrate base 'base' and iterated log base 'base'. - public layeradd(diff: number, base: DecimalSource): Decimal { + public layeradd(diff: number, base: DecimalSource, linear = false): Decimal { const slogthis = this.slog(base).toNumber(); const slogdest = slogthis + diff; if (slogdest >= 0) { - return Decimal.tetrate(base, slogdest); + return Decimal.tetrate(base, slogdest, Decimal.dOne, linear); } else if (!Number.isFinite(slogdest)) { return Decimal.dNaN; } else if (slogdest >= -1) { - return Decimal.log(Decimal.tetrate(base, slogdest + 1), base); + return Decimal.log(Decimal.tetrate(base, slogdest + 1, Decimal.dOne, linear), base); } else { - return Decimal.log(Decimal.log(Decimal.tetrate(base, slogdest + 2), base), base); + return Decimal.log(Decimal.log(Decimal.tetrate(base, slogdest + 2, Decimal.dOne, linear), base), base); } } @@ -2723,9 +2805,311 @@ export default class Decimal { return lnx.div(lnx.lambertw()); } + //Super-root, one of tetration's inverses - what number, tetrated to height (height), equals this? + //Only works with the linear approximation, because I don't know the structure of non-linear tetrations for inputs < 1 + //TODO: Optimize this like how slog is optimized + public linear_sroot(degree: number) : Decimal { + //1st-degree super root just returns its input + if (degree == 1) { + return this; + } + if (this.eq(Decimal.dInf)) { + return Decimal.dInf; + } + if (!this.isFinite()) { + return Decimal.dNaN; + } + //ssqrt handles square super-root faster + if (degree == 2) { + try { + //ssqrt uses lambertw which throws an error if the number is too small + return this.ssqrt(); + } + catch { + return Decimal.dNaN; + } + } + //Using linear approximation, x^^n = x^n if 0 < n < 1 + if (degree > 0 && degree < 1) { + return this.root(degree); + } + //Using the linear approximation, there actually is a single solution for super roots with -2 < degree <= -1 + if (degree > -2 && degree < -1) { + return Decimal.fromNumber(degree).add(2).pow(this.recip()); + } + //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; + } + //Infinite degree super-root is x^(1/x) between 1/e <= x <= e, undefined otherwise + if (degree == Number.POSITIVE_INFINITY) { + const this_num = this.toNumber(); + if (this_num < Math.E && this_num > _EXPN1) { + return this.pow(this.recip()); + } + else { + return Decimal.dNaN; + } + } + //Special case: any super-root of 1 is 1 + if (this.eq(1)) { + return Decimal.dOne; + } + //TODO: base < 0 (It'll probably be NaN anyway) + if (this.lt(0)) { + return Decimal.dNaN; + } + //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; + } + //this > 1 + if (this.gt(1)) { + //Uses guess-and-check to find the super-root. + //If this > 10^^(degree), then the answer is under iteratedlog(10, degree - 1): for example, ssqrt(x) < log(x, 10) as long as x > 10^10, and linear_sroot(x, 3) < log(log(x, 10), 10) as long as x > 10^10^10 + //On the other hand, if this < 10^^(degree), then clearly the answer is less than 10 + //Since the answer could be a higher-layered number itself (whereas slog's maximum is 1.8e308), the guess-and-check is scaled to the layer of the upper bound, so the guess is set to the average of some higher-layer exponents of the bounds rather than the bounds itself (as taking plain averages on tetrational-scale numbers would go nowhere) + let upperBound = Decimal.dTen; + if (this.gte(Decimal.tetrate(10, degree, 1, true))) { + upperBound = this.iteratedlog(10, degree - 1, true); + } + if (degree <= 1) { + upperBound = this.root(degree); + } + let lower = Decimal.dZero; //This is zero rather than one because we might be on a higher layer, so the lower bound might actually some 10^10^10...^0 + let layer = upperBound.layer; + let upper = upperBound.iteratedlog(10, layer, true); + let previous = upper; + let guess = upper.div(2); + let loopGoing = true; + while (loopGoing) { + guess = lower.add(upper).div(2); + if (Decimal.iteratedexp(10, layer, guess, true).tetrate(degree, 1, true).gt(this)) upper = guess; + else lower = guess; + if (guess.eq(previous)) loopGoing = false; + else previous = guess; + } + return Decimal.iteratedexp(10, layer, guess, true); + } + //0 < this < 1 + else { + //A tetration of decimal degree can potentially have three different portions, as shown at https://www.desmos.com/calculator/ayvqks6mxa, which is a graph of x^^2.05: + //The portion where the function is increasing, extending from a minimum (which may be at x = 0 or at some x between 0 and 1) up to infinity (I'll call this the "increasing" range) + //The portion where the function is decreasing (I'll call this the "decreasing" range) + //A small, steep increasing portion very close to x = 0 (I'll call this the "zero" range) + //If ceiling(degree) is even, then the tetration will either be strictly increasing, or it will have the increasing and decreasing ranges, but not the zero range (because if ceiling(degree) is even, 0^^degree == 1). + //If ceiling(degree) is odd, then the tetration will either be strictly increasing, or it will have all three ranges (because if ceiling(degree) is odd, 0^^degree == 0). + //The existence of these ranges means that a super-root could potentially have two or three valid answers. + //Out of these, we'd prefer the increasing range value if it exists, otherwise we'll take the zero range value (it can't have a decreasing range value if it doesn't have an increasing range value) if the zero range exists. + //It's possible to identify which range that "this" is in: + //If the tetration is decreasing at that point, the point is in the decreasing range. + //If the tetration is increasing at that point and ceiling(degree) is even, the point is in the increasing range since there is no zero range. + //If the tetration is increasing at that point and ceiling(degree) is odd, look at the second derivative at that point. If the second derivative is positive, the point is in the increasing range. If the second derivative is negative, the point is the zero range. + //We need to find the local minimum (separates decreasing and increasing ranges) and the local maximum (separates zero and decreasing ranges). + //(stage) is which stage of the loop we're in: stage 1 is finding the minimum, stage 2 means we're between the stages, and stage 3 is finding the maximum. + //The boundary between the decreasing range and the zero range can be very small, so we want to use layer -1 numbers. Therefore, all numbers involved are log10(recip()) of their actual values. + let stage = 1; + let minimum = FC(1, 10, 1); + let maximum = FC(1, 10, 1); + let lower = FC(1, 10, 1); //eeeeeeeee-10, which is effectively 0; I would use Decimal.dInf but its reciprocal is NaN + let upper = FC(1, 1, -16); //~ 1 - 1e-16 + let prevspan = Decimal.dZero; + let difference = FC(1, 10, 1); + let upperBound = upper.pow10().recip(); + let distance = Decimal.dZero; + let prevPoint = upperBound; + let nextPoint = upperBound; + let evenDegree = (Math.ceil(degree) % 2 == 0); + let range = 0; + let lastValid = FC(1, 10, 1); + let infLoopDetector = false; + let previousUpper = Decimal.dZero; + let decreasingFound = false; + while (stage < 4) { + if (stage == 2) { + //The minimum has been found. If ceiling(degree) is even, there's no zero range and thus no local maximum, so end the loop here. Otherwise, begin finding the maximum. + if (evenDegree) break; + else { + lower = FC(1, 10, 1); + upper = minimum; + stage = 3; + difference = FC(1, 10, 1); + lastValid = FC(1, 10, 1); + } + } + infLoopDetector = false; + while (upper.neq(lower)) { + previousUpper = upper; + if (upper.pow10().recip().tetrate(degree, 1, true).eq(1) && upper.pow10().recip().lt(0.4)) { + upperBound = upper.pow10().recip(); + prevPoint = upper.pow10().recip(); + nextPoint = upper.pow10().recip(); + distance = Decimal.dZero; + range = -1; //This would cause problems with degree < 1 in the linear approximation... but those are already covered as a special case + if (stage == 3) lastValid = upper; + } + else if (upper.pow10().recip().tetrate(degree, 1, true).eq(upper.pow10().recip()) && !evenDegree && upper.pow10().recip().lt(0.4)) { + upperBound = upper.pow10().recip(); + prevPoint = upper.pow10().recip(); + nextPoint = upper.pow10().recip(); + distance = Decimal.dZero; + range = 0; + } + else if (upper.pow10().recip().tetrate(degree, 1, true).eq(upper.pow10().recip().mul(2).tetrate(degree, 1, true))) { + //If the upper bound is closer to zero than the next point with a discernable tetration, so surely it's in whichever range is closest to zero? + //This won't happen in a strictly increasing tetration, as there x^^degree ~= x as x approaches zero + upperBound = upper.pow10().recip(); + prevPoint = Decimal.dZero; + nextPoint = upperBound.mul(2); + distance = upperBound; + if (evenDegree) range = -1; + else range = 0; + } + else { + //We want to use prevspan to find the "previous point" right before the upper bound and the "next point" right after the upper bound, as that will let us approximate derivatives + prevspan = upper.mul(1.2e-16); + upperBound = upper.pow10().recip(); + prevPoint = upper.add(prevspan).pow10().recip(); + distance = upperBound.sub(prevPoint); + nextPoint = upperBound.add(distance); + //...but it's of no use to us while its tetration is equal to upper's tetration, so widen the difference until it's not + //We add prevspan and subtract nextspan because, since upper is log10(recip(upper bound)), the upper bound gets smaller as upper gets larger and vice versa + while (prevPoint.tetrate(degree, 1, true).eq(upperBound.tetrate(degree, 1, true)) || nextPoint.tetrate(degree, 1, true).eq(upperBound.tetrate(degree, 1, true)) || prevPoint.gte(upperBound) || nextPoint.lte(upperBound)) { + prevspan = prevspan.mul(2); + prevPoint = upper.add(prevspan).pow10().recip(); + distance = upperBound.sub(prevPoint); + nextPoint = upperBound.add(distance); + } + if ( + stage == 1 && (nextPoint.tetrate(degree, 1, true).gt(upperBound.tetrate(degree, 1, true)) && prevPoint.tetrate(degree, 1, true).gt(upperBound.tetrate(degree, 1, true))) + || + stage == 3 && (nextPoint.tetrate(degree, 1, true).lt(upperBound.tetrate(degree, 1, true)) && prevPoint.tetrate(degree, 1, true).lt(upperBound.tetrate(degree, 1, true))) + ) { + lastValid = upper; + } + if (nextPoint.tetrate(degree, 1, true).lt(upperBound.tetrate(degree, 1, true))) { + //Derivative is negative, so we're in decreasing range + range = -1; + } + else if (evenDegree) { + //No zero range, so we're in increasing range + range = 1; + } + else if (stage == 3 && upper.gt_tolerance(minimum, 1e-8)) { + //We're already below the minimum, so we can't be in range 1 + range = 0; + } + else { + //Number imprecision has left the second derivative somewhat untrustworthy, so we need to expand the bounds to ensure it's correct + while (prevPoint.tetrate(degree, 1, true).eq_tolerance(upperBound.tetrate(degree, 1, true), 1e-8) || nextPoint.tetrate(degree, 1, true).eq_tolerance(upperBound.tetrate(degree, 1, true), 1e-8) || prevPoint.gte(upperBound) || nextPoint.lte(upperBound)) { + prevspan = prevspan.mul(2); + prevPoint = upper.add(prevspan).pow10().recip(); + distance = upperBound.sub(prevPoint); + nextPoint = upperBound.add(distance); + } + if (nextPoint.tetrate(degree, 1, true).sub(upperBound.tetrate(degree, 1, true)).lt(upperBound.tetrate(degree, 1, true).sub(prevPoint.tetrate(degree, 1, true)))) { + //Second derivative is negative, so we're in zero range + range = 0; + } + else { + //By process of elimination, we're in increasing range + range = 1; + } + } + } + if (range == -1) decreasingFound = true; + if ((stage == 1 && range == 1) || (stage == 3 && range != 0)) { + //The upper bound is too high + if (lower.eq(FC(1, 10, 1))) { + upper = upper.mul(2); + } + else { + let cutOff = false; + if (infLoopDetector && ((range == 1 && stage == 1) || (range == -1 && stage == 3))) cutOff = true; //Avoids infinite loops from floating point imprecision + upper = upper.add(lower).div(2); + if (cutOff) break; + } + } + else { + if (lower.eq(FC(1, 10, 1))) { + //We've now found an actual lower bound + lower = upper; + upper = upper.div(2); + } + else { + //The upper bound is too low, meaning last time we decreased the upper bound, we should have gone to the other half of the new range instead + let cutOff = false; + if (infLoopDetector && ((range == 1 && stage == 1) || (range == -1 && stage == 3))) cutOff = true; //Avoids infinite loops from floating point imprecision + lower = lower.sub(difference); + upper = upper.sub(difference); + if (cutOff) break; + } + } + if (lower.sub(upper).div(2).abs().gt(difference.mul(1.5))) infLoopDetector = true; + difference = lower.sub(upper).div(2).abs(); + if (upper.gt("1e18")) break; + if (upper.eq(previousUpper)) break; //Another infinite loop catcher + } + if (upper.gt("1e18")) break; + if (!decreasingFound) break; //If there's no decreasing range, then even if an error caused lastValid to gain a value, the minimum can't exist + if (lastValid == FC(1, 10, 1)) { + //Whatever we're searching for, it doesn't exist. If there's no minimum, then there's no maximum either, so either way we can end the loop here. + break; + } + if (stage == 1) minimum = lastValid; + else if (stage == 3) maximum = lastValid; + stage++; + } + //Now we have the minimum and maximum, so it's time to calculate the actual super-root. + //First, check if the root is in the increasing range. + lower = minimum; + upper = FC(1, 1, -18); + let previous = upper; + let guess = Decimal.dZero; + let loopGoing = true; + while (loopGoing) { + 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; + } + //using guess.neq(minimum) led to imprecision errors, so here's a fixed version of that + if (!(guess.eq_tolerance(minimum, 1e-15))) { + return guess.pow10().recip(); + } + else { + //If guess == minimum, we haven't actually found the super-root, the algorithm just kept going down trying to find a super-root that's not in the increasing range. + //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; + } + lower = FC(1, 10, 1); + upper = maximum; + previous = upper; + guess = Decimal.dZero; + loopGoing = true; + while (loopGoing) { + 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; + } + return guess.pow10().recip(); + } + } + } + //Pentation/pentate: The result of tetrating 'height' times in a row. An absurdly strong operator - Decimal.pentate(2, 4.28) and Decimal.pentate(10, 2.37) are already too huge for break_eternity.js! // https://en.wikipedia.org/wiki/Pentation - public pentate(height = 2, payload: DecimalSource = FC_NN(1, 0, 1)): Decimal { + public pentate(height = 2, payload: DecimalSource = FC_NN(1, 0, 1), linear = false): Decimal { payload = D(payload); const oldheight = height; height = Math.trunc(height); @@ -2738,15 +3122,15 @@ export default class Decimal { payload = Decimal.fromNumber(fracheight); } else { if (this.eq(10)) { - payload = payload.layeradd10(fracheight); + payload = payload.layeradd10(fracheight, linear); } else { - payload = payload.layeradd(fracheight, this); + payload = payload.layeradd(fracheight, this, linear); } } } for (let i = 0; i < height; ++i) { - payload = this.tetrate(payload.toNumber()); + payload = this.tetrate(payload.toNumber(), Decimal.dOne, linear); //bail if we're NaN if (!isFinite(payload.layer) || !isFinite(payload.mag)) { return payload.normalize(); @@ -2896,4 +3280,4 @@ FC_NN = Decimal.fromComponents_noNormalize; // eslint-disable-next-line @typescript-eslint/no-unused-vars ME = Decimal.fromMantissaExponent; // eslint-disable-next-line @typescript-eslint/no-unused-vars -ME_NN = Decimal.fromMantissaExponent_noNormalize; +ME_NN = Decimal.fromMantissaExponent_noNormalize; \ No newline at end of file diff --git a/src/unit_tests.js b/src/unit_tests.js index 3dc55db..5e3b5e9 100644 --- a/src/unit_tests.js +++ b/src/unit_tests.js @@ -90,7 +90,9 @@ var test_tetrate_slog = function() let base = Math.random()*10 + 1.5; let tower = Math.random()*10 - 1; let round_trip = new Decimal(base).tetrate(tower).slog(base).toNumber(); - assert_eq_tolerance(base + ", " + tower, round_trip, tower, base < 2 ? 1e-2 : 1e-10); + 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); } } @@ -266,6 +268,76 @@ var test_pow_root = function() } } +var test_tetrate_linear_truth = function() +{ + console.log("test_tetrate_linear_truth") + assert_eq_tolerance(10.5, new Decimal(10).tetrate(10.5, 1, true), new Decimal("(e^9)1453.0403018990435")) + assert_eq_tolerance(10, new Decimal(10).tetrate(10, 1, true), new Decimal("(e^8)10000000000")) + assert_eq_tolerance(4, new Decimal(10).tetrate(4, 1, true), new Decimal("ee10000000000")) + assert_eq_tolerance(3.5, new Decimal(10).tetrate(3.5, 1, true), new Decimal("e1.0972406760e1453")) + assert_eq_tolerance(3, new Decimal(10).tetrate(3, 1, true), new Decimal("1e10000000000")) + assert_eq_tolerance(2.5, new Decimal(10).tetrate(2.5, 1, true), new Decimal("1.0972406760e1453")) + assert_eq_tolerance(2, new Decimal(10).tetrate(2, 1, true), 1e10) + assert_eq_tolerance(1.5, new Decimal(10).tetrate(1.5, 1, true), 1453.0403018990435) + assert_eq_tolerance(1.1, new Decimal(10).tetrate(1.1, 1, true), 18.152038825555795) + assert_eq_tolerance(1.09, new Decimal(10).tetrate(1.09, 1, true), 16.992949658256496, 1e-3) + assert_eq_tolerance(1.05, new Decimal(10).tetrate(1.05, 1, true), 13.243978111062273, 1e-3) + assert_eq_tolerance(1.01, new Decimal(10).tetrate(1.01, 1, true), 10.550984676065603, 1e-3) + assert_eq_tolerance(1, new Decimal(10).tetrate(1, 1, true), 10) + assert_eq_tolerance(0.99, new Decimal(10).tetrate(0.99, 1, true), 9.772372209558107, 1e-2) + assert_eq_tolerance(0.95, new Decimal(10).tetrate(0.95, 1, true), 8.912509381337454, 1e-2) + assert_eq_tolerance(0.91, new Decimal(10).tetrate(0.91, 1, true), 8.128305161640993, 1e-2) + assert_eq_tolerance(0.5, new Decimal(10).tetrate(0.5, 1, true), 3.1622776601683795) + assert_eq_tolerance(-1, new Decimal(10).tetrate(-1, 1, true), 0) + assert_eq_tolerance(-1.1, new Decimal(10).tetrate(-1.1, 1, true), -0.045757490560675115) + assert_eq_tolerance(-1.5, new Decimal(10).tetrate(-1.5, 1, true), -0.30102999566398114) + assert_eq_tolerance(-1.9, new Decimal(10).tetrate(-1.9, 1, true), -1) + assert_eq_tolerance(-1.99, new Decimal(10).tetrate(-1.99, 1, true), -2) + assert_eq_tolerance(-1.999, new Decimal(10).tetrate(-1.999, 1, true), -3) + assert_eq_tolerance(-1.9999, new Decimal(10).tetrate(-1.9999, 1, true), -4) + assert_eq_tolerance(-1.99999, new Decimal(10).tetrate(-1.99999, 1, true), -5) + assert_eq_tolerance(-2, new Decimal(10).tetrate(-2, 1, true), Number.NaN) + assert_eq_tolerance(-2.1, new Decimal(10).tetrate(-2.1, 1, true), Number.NaN) +} + +var test_modulo = function() { + console.log("test_modulo"); + for (var i = 0; i < 1000; ++i) + { + var a = Decimal.pow(10, Math.random() * 15); + var b = Decimal.pow(10, Math.random() * 15); + if (Math.random() > 0.5 && a.sign !== 0) { a = a.recip(); } + if (Math.random() > 0.5 && b.sign !== 0) { b = b.recip(); } + if (Math.random() > 0.5) { a = a.neg(); } + if (Math.random() > 0.5) { b = b.neg(); } + var c = a.mod(b); + var d = a.abs().div(b.abs()).floor().mul(b.abs()).add(c.abs()).mul(a.sgn()); + assert_eq_tolerance(a + ", " + b + " -> " + c + ", " + d, d, a, 1e-5); + } +} + +var test_tetrate_linear_sroot = function() +{ + console.log("test_tetrate_linear_sroot"); + 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(); + degree = Math.random()*10; + if (base.eq(0)) base = Decimal.dOne; + let round_trip = new Decimal(base).linear_sroot(degree).tetrate(degree, 1, true); + if (!round_trip.isFinite()) continue; + assert_eq_tolerance(base + ", " + degree + " -> " + round_trip, round_trip, base); + } + catch (err) { + console.log("Error in " + base + ", " + degree + ": " + err); + } + } +} + var all_tests = function() { test_tetrate_ground_truth(); @@ -283,4 +355,7 @@ var all_tests = function() test_add_number(); test_mul(); test_pow_root(); + test_tetrate_linear_truth(); + test_modulo(); + test_tetrate_linear_sroot(); } \ No newline at end of file