UNPKG

@cortex-js/compute-engine

Version:

Symbolic computing and numeric evaluations for JavaScript and Node.js

1,685 lines (1,682 loc) 2.23 MB
/** Compute Engine 0.58.0 */ // node_modules/complex-esm/dist/src/complex.js var cosh = Math.cosh || function(x) { return Math.abs(x) < 1e-9 ? 1 - x : (Math.exp(x) + Math.exp(-x)) * 0.5; }; var sinh = Math.sinh || function(x) { return Math.abs(x) < 1e-9 ? x : (Math.exp(x) - Math.exp(-x)) * 0.5; }; var cosm1 = function(x) { var b = Math.PI / 4; if (-b > x || x > b) { return Math.cos(x) - 1; } var xx = x * x; return xx * (xx * (xx * (xx * (xx * (xx * (xx * (xx / 20922789888e3 - 1 / 87178291200) + 1 / 479001600) - 1 / 3628800) + 1 / 40320) - 1 / 720) + 1 / 24) - 1 / 2); }; var hypot = function(x, y) { var a = Math.abs(x); var b = Math.abs(y); if (a < 3e3 && b < 3e3) { return Math.sqrt(a * a + b * b); } if (a < b) { a = b; b = x / y; } else { b = y / x; } return a * Math.sqrt(1 + b * b); }; var parser_exit = function() { throw SyntaxError("Invalid Param"); }; function logHypot(a, b) { var _a = Math.abs(a); var _b = Math.abs(b); if (a === 0) { return Math.log(_b); } if (b === 0) { return Math.log(_a); } if (_a < 3e3 && _b < 3e3) { return Math.log(a * a + b * b) * 0.5; } a = a / 2; b = b / 2; return 0.5 * Math.log(a * a + b * b) + Math.LN2; } var parse = function(a, b) { var z = { "re": 0, "im": 0 }; if (a === void 0 || a === null) { z["re"] = z["im"] = 0; } else if (b !== void 0) { z["re"] = a; z["im"] = b; } else switch (typeof a) { case "object": if ("im" in a && "re" in a) { z["re"] = a["re"]; z["im"] = a["im"]; } else if ("abs" in a && "arg" in a) { if (!Number.isFinite(a["abs"]) && Number.isFinite(a["arg"])) { return Complex["INFINITY"]; } z["re"] = a["abs"] * Math.cos(a["arg"]); z["im"] = a["abs"] * Math.sin(a["arg"]); } else if ("r" in a && "phi" in a) { if (!Number.isFinite(a["r"]) && Number.isFinite(a["phi"])) { return Complex["INFINITY"]; } z["re"] = a["r"] * Math.cos(a["phi"]); z["im"] = a["r"] * Math.sin(a["phi"]); } else if (a.length === 2) { z["re"] = a[0]; z["im"] = a[1]; } else { parser_exit(); } break; case "string": z["im"] = /* void */ z["re"] = 0; var tokens = a.match(/\d+\.?\d*e[+-]?\d+|\d+\.?\d*|\.\d+|./g); var plus = 1; var minus = 0; if (tokens === null) { parser_exit(); } for (var i = 0; i < tokens.length; i++) { var c = tokens[i]; if (c === " " || c === " " || c === "\n") { } else if (c === "+") { plus++; } else if (c === "-") { minus++; } else if (c === "i" || c === "I") { if (plus + minus === 0) { parser_exit(); } if (tokens[i + 1] !== " " && !isNaN(Number(tokens[i + 1]))) { z["im"] += parseFloat((minus % 2 ? "-" : "") + tokens[i + 1]); i++; } else { z["im"] += parseFloat((minus % 2 ? "-" : "") + "1"); } plus = minus = 0; } else { if (plus + minus === 0 || isNaN(Number(c))) { parser_exit(); } if (tokens[i + 1] === "i" || tokens[i + 1] === "I") { z["im"] += parseFloat((minus % 2 ? "-" : "") + c); i++; } else { z["re"] += parseFloat((minus % 2 ? "-" : "") + c); } plus = minus = 0; } } if (plus + minus > 0) { parser_exit(); } break; case "number": z["im"] = 0; z["re"] = a; break; default: parser_exit(); } if (isNaN(z["re"]) || isNaN(z["im"])) { } return z; }; var Complex = class _Complex { constructor(a, b) { this.re = 0; this.im = 0; var z = parse(a, b); this["re"] = z["re"]; this["im"] = z["im"]; } /** * Calculates the sign of a complex number, which is a normalized complex * * @returns {Complex} */ sign() { var abs2 = this["abs"](); return new _Complex(this["re"] / abs2, this["im"] / abs2); } /** * Adds two complex numbers * * @returns {Complex} */ add(a, b) { var z = new _Complex(a, b); if (this["isInfinite"]() && z["isInfinite"]()) { return _Complex["NAN"]; } if (this["isInfinite"]() || z["isInfinite"]()) { return _Complex["INFINITY"]; } return new _Complex(this["re"] + z["re"], this["im"] + z["im"]); } /** * Subtracts two complex numbers * * @returns {Complex} */ sub(a, b) { var z = new _Complex(a, b); if (this["isInfinite"]() && z["isInfinite"]()) { return _Complex["NAN"]; } if (this["isInfinite"]() || z["isInfinite"]()) { return _Complex["INFINITY"]; } return new _Complex(this["re"] - z["re"], this["im"] - z["im"]); } /** * Multiplies two complex numbers * * @returns {Complex} */ mul(a, b) { var z = new _Complex(a, b); if (this["isInfinite"]() && z["isZero"]() || this["isZero"]() && z["isInfinite"]()) { return _Complex["NAN"]; } if (this["isInfinite"]() || z["isInfinite"]()) { return _Complex["INFINITY"]; } if (z["im"] === 0 && this["im"] === 0) { return new _Complex(this["re"] * z["re"], 0); } return new _Complex(this["re"] * z["re"] - this["im"] * z["im"], this["re"] * z["im"] + this["im"] * z["re"]); } /** * Divides two complex numbers * * @returns {Complex} */ div(a, b) { var z = new _Complex(a, b); if (this["isZero"]() && z["isZero"]() || this["isInfinite"]() && z["isInfinite"]()) { return _Complex["NAN"]; } if (this["isInfinite"]() || z["isZero"]()) { return _Complex["INFINITY"]; } if (this["isZero"]() || z["isInfinite"]()) { return _Complex["ZERO"]; } a = this["re"]; b = this["im"]; var c = z["re"]; var d = z["im"]; var t, x; if (0 === d) { return new _Complex(a / c, b / c); } if (Math.abs(c) < Math.abs(d)) { x = c / d; t = c * x + d; return new _Complex((a * x + b) / t, (b * x - a) / t); } else { x = d / c; t = d * x + c; return new _Complex((a + b * x) / t, (b - a * x) / t); } } /** * Calculate the power of two complex numbers * * @returns {Complex} */ pow(a, b) { var z = new _Complex(a, b); a = this["re"]; b = this["im"]; if (z["isZero"]()) { return _Complex["ONE"]; } if (z["im"] === 0) { if (b === 0 && a > 0) { return new _Complex(Math.pow(a, z["re"]), 0); } else if (a === 0) { switch ((z["re"] % 4 + 4) % 4) { case 0: return new _Complex(Math.pow(b, z["re"]), 0); case 1: return new _Complex(0, Math.pow(b, z["re"])); case 2: return new _Complex(-Math.pow(b, z["re"]), 0); case 3: return new _Complex(0, -Math.pow(b, z["re"])); } } } if (a === 0 && b === 0 && z["re"] > 0 && z["im"] >= 0) { return _Complex["ZERO"]; } var arg = Math.atan2(b, a); var loh = logHypot(a, b); a = Math.exp(z["re"] * loh - z["im"] * arg); b = z["im"] * loh + z["re"] * arg; return new _Complex(a * Math.cos(b), a * Math.sin(b)); } /** * Calculate the complex square root * * @returns {Complex} */ sqrt() { var a = this["re"]; var b = this["im"]; var r = this["abs"](); var re, im; if (a >= 0) { if (b === 0) { return new _Complex(Math.sqrt(a), 0); } re = 0.5 * Math.sqrt(2 * (r + a)); } else { re = Math.abs(b) / Math.sqrt(2 * (r - a)); } if (a <= 0) { im = 0.5 * Math.sqrt(2 * (r - a)); } else { im = Math.abs(b) / Math.sqrt(2 * (r + a)); } return new _Complex(re, b < 0 ? -im : im); } /** * Calculate the complex exponent * * @returns {Complex} */ exp() { var tmp = Math.exp(this["re"]); if (this["im"] === 0) { } return new _Complex(tmp * Math.cos(this["im"]), tmp * Math.sin(this["im"])); } /** * Calculate the complex exponent and subtracts one. * * This may be more accurate than `Complex(x).exp().sub(1)` if * `x` is small. * * @returns {Complex} */ expm1() { var a = this["re"]; var b = this["im"]; return new _Complex(Math.expm1(a) * Math.cos(b) + cosm1(b), Math.exp(a) * Math.sin(b)); } /** * Calculate the natural log * * @returns {Complex} */ log() { var a = this["re"]; var b = this["im"]; if (b === 0 && a > 0) { } return new _Complex(logHypot(a, b), Math.atan2(b, a)); } /** * Calculate the magnitude of the complex number * * @returns {number} */ abs() { return hypot(this["re"], this["im"]); } /** * Calculate the angle of the complex number * * @returns {number} */ arg() { return Math.atan2(this["im"], this["re"]); } /** * Calculate the sine of the complex number * * @returns {Complex} */ sin() { var a = this["re"]; var b = this["im"]; return new _Complex(Math.sin(a) * cosh(b), Math.cos(a) * sinh(b)); } /** * Calculate the cosine * * @returns {Complex} */ cos() { var a = this["re"]; var b = this["im"]; return new _Complex(Math.cos(a) * cosh(b), -Math.sin(a) * sinh(b)); } /** * Calculate the tangent * * @returns {Complex} */ tan() { var a = 2 * this["re"]; var b = 2 * this["im"]; var d = Math.cos(a) + cosh(b); return new _Complex(Math.sin(a) / d, sinh(b) / d); } /** * Calculate the cotangent * * @returns {Complex} */ cot() { var a = 2 * this["re"]; var b = 2 * this["im"]; var d = Math.cos(a) - cosh(b); return new _Complex(-Math.sin(a) / d, sinh(b) / d); } /** * Calculate the secant * * @returns {Complex} */ sec() { var a = this["re"]; var b = this["im"]; var d = 0.5 * cosh(2 * b) + 0.5 * Math.cos(2 * a); return new _Complex(Math.cos(a) * cosh(b) / d, Math.sin(a) * sinh(b) / d); } /** * Calculate the cosecans * * @returns {Complex} */ csc() { var a = this["re"]; var b = this["im"]; var d = 0.5 * cosh(2 * b) - 0.5 * Math.cos(2 * a); return new _Complex(Math.sin(a) * cosh(b) / d, -Math.cos(a) * sinh(b) / d); } /** * Calculate the complex arcus sinus * * @returns {Complex} */ asin() { var a = this["re"]; var b = this["im"]; var t1 = new _Complex(b * b - a * a + 1, -2 * a * b)["sqrt"](); var t2 = new _Complex(t1["re"] - b, t1["im"] + a)["log"](); return new _Complex(t2["im"], -t2["re"]); } /** * Calculate the complex arcus cosinus * * @returns {Complex} */ acos() { var a = this["re"]; var b = this["im"]; var t1 = new _Complex(b * b - a * a + 1, -2 * a * b)["sqrt"](); var t2 = new _Complex(t1["re"] - b, t1["im"] + a)["log"](); return new _Complex(Math.PI / 2 - t2["im"], t2["re"]); } /** * Calculate the complex arcus tangent * * @returns {Complex} */ atan() { var a = this["re"]; var b = this["im"]; if (a === 0) { if (b === 1) { return new _Complex(0, Infinity); } if (b === -1) { return new _Complex(0, -Infinity); } } var d = a * a + (1 - b) * (1 - b); var t1 = new _Complex((1 - b * b - a * a) / d, -2 * a / d).log(); return new _Complex(-0.5 * t1["im"], 0.5 * t1["re"]); } /** * Calculate the complex arcus cotangent * * @returns {Complex} */ acot() { var a = this["re"]; var b = this["im"]; if (b === 0) { return new _Complex(Math.atan2(1, a), 0); } var d = a * a + b * b; return d !== 0 ? new _Complex(a / d, -b / d).atan() : new _Complex(a !== 0 ? a / 0 : 0, b !== 0 ? -b / 0 : 0).atan(); } /** * Calculate the complex arcus secant * * @returns {Complex} */ asec() { var a = this["re"]; var b = this["im"]; if (a === 0 && b === 0) { return new _Complex(0, Infinity); } var d = a * a + b * b; return d !== 0 ? new _Complex(a / d, -b / d).acos() : new _Complex(a !== 0 ? a / 0 : 0, b !== 0 ? -b / 0 : 0).acos(); } /** * Calculate the complex arcus cosecans * * @returns {Complex} */ acsc() { var a = this["re"]; var b = this["im"]; if (a === 0 && b === 0) { return new _Complex(Math.PI / 2, Infinity); } var d = a * a + b * b; return d !== 0 ? new _Complex(a / d, -b / d).asin() : new _Complex(a !== 0 ? a / 0 : 0, b !== 0 ? -b / 0 : 0).asin(); } /** * Calculate the complex sinh * * @returns {Complex} */ sinh() { var a = this["re"]; var b = this["im"]; return new _Complex(sinh(a) * Math.cos(b), cosh(a) * Math.sin(b)); } /** * Calculate the complex cosh * * @returns {Complex} */ cosh() { var a = this["re"]; var b = this["im"]; return new _Complex(cosh(a) * Math.cos(b), sinh(a) * Math.sin(b)); } /** * Calculate the complex tanh * * @returns {Complex} */ tanh() { var a = 2 * this["re"]; var b = 2 * this["im"]; var d = cosh(a) + Math.cos(b); return new _Complex(sinh(a) / d, Math.sin(b) / d); } /** * Calculate the complex coth * * @returns {Complex} */ coth() { var a = 2 * this["re"]; var b = 2 * this["im"]; var d = cosh(a) - Math.cos(b); return new _Complex(sinh(a) / d, -Math.sin(b) / d); } /** * Calculate the complex coth * * @returns {Complex} */ csch() { var a = this["re"]; var b = this["im"]; var d = Math.cos(2 * b) - cosh(2 * a); return new _Complex(-2 * sinh(a) * Math.cos(b) / d, 2 * cosh(a) * Math.sin(b) / d); } /** * Calculate the complex sech * * @returns {Complex} */ sech() { var a = this["re"]; var b = this["im"]; var d = Math.cos(2 * b) + cosh(2 * a); return new _Complex(2 * cosh(a) * Math.cos(b) / d, -2 * sinh(a) * Math.sin(b) / d); } /** * Calculate the complex asinh * * @returns {Complex} */ asinh() { var tmp = this["im"]; this["im"] = -this["re"]; this["re"] = tmp; var res = this["asin"](); this["re"] = -this["im"]; this["im"] = tmp; tmp = res["re"]; res["re"] = -res["im"]; res["im"] = tmp; return res; } /** * Calculate the complex acosh * * @returns {Complex} */ acosh() { var res = this["acos"](); if (res["im"] <= 0) { var tmp = res["re"]; res["re"] = -res["im"]; res["im"] = tmp; } else { var tmp = res["im"]; res["im"] = -res["re"]; res["re"] = tmp; } return res; } /** * Calculate the complex atanh * * @returns {Complex} */ atanh() { var a = this["re"]; var b = this["im"]; var noIM = a > 1 && b === 0; var oneMinus = 1 - a; var onePlus = 1 + a; var d = oneMinus * oneMinus + b * b; var x = d !== 0 ? new _Complex((onePlus * oneMinus - b * b) / d, (b * oneMinus + onePlus * b) / d) : new _Complex(a !== -1 ? a / 0 : 0, b !== 0 ? b / 0 : 0); var temp = x["re"]; x["re"] = logHypot(x["re"], x["im"]) / 2; x["im"] = Math.atan2(x["im"], temp) / 2; if (noIM) { x["im"] = -x["im"]; } return x; } /** * Calculate the complex acoth * * @returns {Complex} */ acoth() { var a = this["re"]; var b = this["im"]; if (a === 0 && b === 0) { return new _Complex(0, Math.PI / 2); } var d = a * a + b * b; return d !== 0 ? new _Complex(a / d, -b / d).atanh() : new _Complex(a !== 0 ? a / 0 : 0, b !== 0 ? -b / 0 : 0).atanh(); } /** * Calculate the complex acsch * * @returns {Complex} */ acsch() { var a = this["re"]; var b = this["im"]; if (b === 0) { return new _Complex(a !== 0 ? Math.log(a + Math.sqrt(a * a + 1)) : Infinity, 0); } var d = a * a + b * b; return d !== 0 ? new _Complex(a / d, -b / d).asinh() : new _Complex(a !== 0 ? a / 0 : 0, b !== 0 ? -b / 0 : 0).asinh(); } /** * Calculate the complex asech * * @returns {Complex} */ asech() { var a = this["re"]; var b = this["im"]; if (this["isZero"]()) { return _Complex["INFINITY"]; } var d = a * a + b * b; return d !== 0 ? new _Complex(a / d, -b / d).acosh() : new _Complex(a !== 0 ? a / 0 : 0, b !== 0 ? -b / 0 : 0).acosh(); } /** * Calculate the complex inverse 1/z * * @returns {Complex} */ inverse() { if (this["isZero"]()) { return _Complex["INFINITY"]; } if (this["isInfinite"]()) { return _Complex["ZERO"]; } var a = this["re"]; var b = this["im"]; var d = a * a + b * b; return new _Complex(a / d, -b / d); } /** * Returns the complex conjugate * * @returns {Complex} */ conjugate() { return new _Complex(this["re"], -this["im"]); } /** * Gets the negated complex number * * @returns {Complex} */ neg() { return new _Complex(-this["re"], -this["im"]); } /** * Ceils the actual complex number * * @returns {Complex} */ ceil(places) { places = Math.pow(10, places || 0); return new _Complex(Math.ceil(this["re"] * places) / places, Math.ceil(this["im"] * places) / places); } /** * Floors the actual complex number * * @returns {Complex} */ floor(places) { places = Math.pow(10, places || 0); return new _Complex(Math.floor(this["re"] * places) / places, Math.floor(this["im"] * places) / places); } /** * Ceils the actual complex number * * @returns {Complex} */ round(places) { places = Math.pow(10, places || 0); return new _Complex(Math.round(this["re"] * places) / places, Math.round(this["im"] * places) / places); } /** * Compares two complex numbers * * **Note:** new Complex(Infinity).equals(Infinity) === false * * @returns {boolean} */ equals(a, b) { var z = new _Complex(a, b); return Math.abs(z["re"] - this["re"]) <= _Complex["EPSILON"] && Math.abs(z["im"] - this["im"]) <= _Complex["EPSILON"]; } /** * Clones the actual object * * @returns {Complex} */ clone() { return new _Complex(this["re"], this["im"]); } /** * Gets a string of the actual complex number * * @returns {string} */ toString() { var a = this["re"]; var b = this["im"]; var ret = ""; if (this["isNaN"]()) { return "NaN"; } if (this["isInfinite"]()) { return "Infinity"; } if (Math.abs(a) < _Complex["EPSILON"]) { a = 0; } if (Math.abs(b) < _Complex["EPSILON"]) { b = 0; } if (b === 0) { return ret + a; } if (a !== 0) { ret += a; ret += " "; if (b < 0) { b = -b; ret += "-"; } else { ret += "+"; } ret += " "; } else if (b < 0) { b = -b; ret += "-"; } if (1 !== b) { ret += b; } return ret + "i"; } /** * Returns the actual number as a vector * * @returns {Array} */ toVector() { return [this["re"], this["im"]]; } /** * Returns the actual real value of the current object * * @returns {number|null} */ valueOf() { if (this["im"] === 0) { return this["re"]; } return null; } /** * Determines whether a complex number is not on the Riemann sphere. * * @returns {boolean} */ isNaN() { return isNaN(this["re"]) || isNaN(this["im"]); } /** * Determines whether or not a complex number is at the zero pole of the * Riemann sphere. * * @returns {boolean} */ isZero() { return this["im"] === 0 && this["re"] === 0; } /** * Determines whether a complex number is not at the infinity pole of the * Riemann sphere. * * @returns {boolean} */ isFinite() { return isFinite(this["re"]) && isFinite(this["im"]); } /** * Determines whether or not a complex number is at the infinity pole of the * Riemann sphere. * * @returns {boolean} */ isInfinite() { return !(this["isNaN"]() || this["isFinite"]()); } }; Complex["ZERO"] = new Complex(0, 0); Complex["ONE"] = new Complex(1, 0); Complex["I"] = new Complex(0, 1); Complex["PI"] = new Complex(Math.PI, 0); Complex["E"] = new Complex(Math.E, 0); Complex["INFINITY"] = new Complex(Infinity, Infinity); Complex["NAN"] = new Complex(NaN, NaN); Complex["EPSILON"] = 1e-15; // src/big-decimal/utils.ts var _pow10Cache = /* @__PURE__ */ new Map(); function pow10(n) { if (n <= 100) { let v = _pow10Cache.get(n); if (v === void 0) { v = 10n ** BigInt(n); _pow10Cache.set(n, v); } return v; } return 10n ** BigInt(n); } function fpmul(a, b, scale) { return a * b / scale; } function fpdiv(a, b, scale) { return a * scale / b; } function fpsqrt(a, scale) { if (a === 0n) return 0n; if (a < 0n) throw new RangeError("fpsqrt: negative input"); let x; const aNum = Number(a); const scaleNum = Number(scale); if (Number.isFinite(aNum) && Number.isFinite(scaleNum) && aNum > 0 && scaleNum > 0) { const approx = Math.sqrt(aNum / scaleNum) * scaleNum; if (Number.isFinite(approx) && approx > 0) { x = BigInt(Math.floor(approx)); if (x === 0n) x = 1n; } else { x = digitBasedSeed(a, scale); } } else { x = digitBasedSeed(a, scale); } const as = a * scale; let prev; do { prev = x; x = (x + as / x) / 2n; } while (bigintAbs(x - prev) > 1n); const next = (x + as / x) / 2n; const diffX = bigintAbs(x * x - as); const diffNext = bigintAbs(next * next - as); return diffNext < diffX ? next : x; } function digitBasedSeed(a, scale) { const LEAD = 15; const digA = bigintDigits(a); const shiftA = Math.max(0, digA - LEAD); const leadA = Number(shiftA > 0 ? a / pow10(shiftA) : a); const digS = bigintDigits(scale); const shiftS = Math.max(0, digS - LEAD); const leadS = Number(shiftS > 0 ? scale / pow10(shiftS) : scale); const totalShift = shiftA + shiftS; const halfShift = Math.floor(totalShift / 2); let floatSeed = Math.sqrt(leadA * leadS); if (totalShift % 2 !== 0) floatSeed *= 3.1622776601683795; const seed = BigInt(Math.round(floatSeed)) * pow10(halfShift); return seed > 0n ? seed : 1n; } function bigintAbs(n) { return n < 0n ? -n : n; } function bigintDigits(n) { if (n === 0n) return 1; if (n < 0n) n = -n; if (n < 0x20000000000000n) return Math.floor(Math.log10(Number(n))) + 1; let bits = 0; let tmp = n; let high = 1; while (tmp >> BigInt(high) > 0n) high *= 2; for (let shift = high >> 1; shift >= 1; shift >>= 1) { if (tmp >> BigInt(shift) > 0n) { bits += shift; tmp >>= BigInt(shift); } } bits += 1; const approx = Math.ceil(bits * 0.30102999566398); if (n < pow10(approx - 1)) return approx - 1; if (n >= pow10(approx)) return approx + 1; return approx; } function fpexp(x, scale) { if (x === 0n) return scale; let k = 0; let r = x; const half = scale / 2n; while (bigintAbs(r) > half) { r = r / 2n; k++; } let sum = scale; let term = r; sum += term; for (let n = 2; ; n++) { term = term * r / (BigInt(n) * scale); if (bigintAbs(term) === 0n) break; sum += term; } for (let i = 0; i < k; i++) { sum = sum * sum / scale; } return sum; } function fpln(x, scale) { if (x === scale) return 0n; const xNum = Number(x); const scaleNum = Number(scale); let y; let target = x; let k = 0; if (Number.isFinite(xNum) && Number.isFinite(scaleNum) && xNum > 0 && scaleNum > 0) { const ratio = xNum / scaleNum; if (Number.isFinite(ratio) && ratio > 0) { const approx = Math.log(ratio); if (Number.isFinite(approx)) { y = BigInt(Math.round(approx * scaleNum)); } else { y = estimateLnSeed(x, scale); } } else { y = estimateLnSeed(x, scale); } } else { target = x; const twoScale = 2n * scale; const halfScale = scale / 2n; while (target > twoScale || target < halfScale) { target = fpsqrt(target, scale); k++; } y = estimateLnSeed(target, scale); } let prevAbsDelta = 0n; for (let i = 0; i < 100; i++) { const ey = fpexp(y, scale); if (ey === 0n) { y = y / 2n; continue; } const yn = y + target * scale / ey - scale; const absDelta = bigintAbs(yn - y); if (absDelta <= 1n) break; if (absDelta < 100000n && prevAbsDelta > 0n && prevAbsDelta < 100000n && absDelta * 4n >= prevAbsDelta) break; prevAbsDelta = absDelta; y = yn; } for (let i = 0; i < k; i++) { y = 2n * y; } return y; } function estimateLnSeed(x, scale) { const xDigits = bigintDigits(x); const scaleDigits = bigintDigits(scale); const digitDiff = BigInt(xDigits - scaleDigits); return digitDiff * 2302585n * scale / 1000000n; } var PI_DIGITS = "314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316527120190914564856692346034861045432664821339360726024914127372458700660631558817488152092096282925409171536436789259036001133053054882046652138414695194151160943305727036575959195309218611738193261179310511854807446237996274956735188575272489122793818301194912983367336244065664308602139494639522473719070217986094370277053921717629317675238467481846766940513200056812714526356082778577134275778960917363717872146844090122495343014654958537105079227968925892354201995611212902196086403441815981362977477130996051870721134999999837297804995105973173281609631859502445945534690830264252230825334468503526193118817101000313783875288658753320838142061717766914730359825349042875546873115956286388235378759375195778185778053217122680661300192787661119590921642019893809525720106548586327886593615338182796823030195203530185296899577362259941389124972177528347913151557485724245415069595082953311686172785588907509838175463746493931925506040092770167113900984882401285836160356370766010471018194295559619894676783744944825537977472684710404753464620804668425906949129331367702898915210475216205696602405803815019351125338243003558764024749647326391419927260426992279678235478163600934172164121992458631503028618297455570674983850549458858692699569092721079750930295532116534498720275596023648066549911988183479775356636980742654252786255181841757467289097777279380008164706001614524919217321721477235014144197356854816136115735255213347574184946843852332390739414333454776241686251898356948556209921922218427255025425688767179049460165346680498862723279178608578438382796797668145410095388378636095068006422512520511739298489608412848862694560424196528502221066118630674427862203919494504712371378696095636437191728746776465757396241389086583264599581339047802759009946576407895126946839835259570982582262052248940772671947826848260147699090264013639443745530506820349625245174939965143142980919065925093722169646151570985838741059788595977297549893016175392846813826868386894277415599185592524595395943104997252468084598727364469584865383673622262609912460805124388439045124413654976278079771569143599770012961608944169486855584840635"; var _fppiCache = null; function fppi(scale) { if (_fppiCache !== null && _fppiCache.scale === scale) return _fppiCache.value; const p = bigintDigits(scale) - 1; const neededDigits = p + 10; const digits = PI_DIGITS.slice(0, neededDigits + 1); const piInt = BigInt(digits); const fracDigits = digits.length - 1; const value = piInt * scale / pow10(fracDigits); _fppiCache = { scale, value }; return value; } function fpsincos(x, scale) { if (x === 0n) return [0n, scale]; const pi = fppi(scale); const twoPi = 2n * pi; const halfPi = pi / 2n; let r; const absX = bigintAbs(x); if (absX > scale * (1n << 30n)) { const extraDigits = bigintDigits(absX) - bigintDigits(scale) + 20; const extScale = scale * pow10(extraDigits); const extX = x * pow10(extraDigits); const extPi = fppi(extScale); const extTwoPi = 2n * extPi; let extR = extX % extTwoPi; if (extR < 0n) extR += extTwoPi; r = extR / pow10(extraDigits); } else { r = x % twoPi; } if (r < 0n) r += twoPi; let sinSign = 1n; let cosSign = 1n; if (r > 3n * halfPi) { r = twoPi - r; sinSign = -1n; } else if (r > pi) { r = r - pi; sinSign = -1n; cosSign = -1n; } else if (r > halfPi) { r = pi - r; cosSign = -1n; } const p = bigintDigits(scale) - 1; const targetK = Math.min(18, Math.max(2, Math.ceil(0.87 * Math.sqrt(p)))); let k = 0; const threshold = scale >> BigInt(targetK); while (r > threshold) { r = r / 2n; k++; } let sinVal = r; let cosVal = scale; let sinTerm = r; let cosTerm = scale; const r2 = r * r; const scale2 = scale * scale; for (let n = 2; ; n += 2) { cosTerm = cosTerm * r2 / (BigInt(n) * BigInt(n - 1) * scale2); if (cosTerm === 0n) { sinTerm = sinTerm * r2 / (BigInt(n + 1) * BigInt(n) * scale2); if (sinTerm !== 0n) { if (n % 4 === 2) { cosVal -= cosTerm; sinVal -= sinTerm; } else { cosVal += cosTerm; sinVal += sinTerm; } } break; } sinTerm = sinTerm * r2 / (BigInt(n + 1) * BigInt(n) * scale2); if (n % 4 === 2) { cosVal -= cosTerm; sinVal -= sinTerm; } else { cosVal += cosTerm; sinVal += sinTerm; } if (sinTerm === 0n) break; } for (let i = 0; i < k; i++) { const newSin = 2n * sinVal * cosVal / scale; const newCos = 2n * cosVal * cosVal / scale - scale; sinVal = newSin; cosVal = newCos; } return [sinSign * sinVal, cosSign * cosVal]; } function fpatan(x, scale) { if (x === 0n) return 0n; if (x < 0n) return -fpatan(-x, scale); const pi = fppi(scale); const halfPi = pi / 2n; if (x > scale) { const reciprocal = scale * scale / x; return halfPi - fpatan(reciprocal, scale); } const threshold = 4n * scale / 10n; let halvings = 0; let r = x; while (r > threshold) { const r22 = r * r; const val = (scale * scale + r22) / scale; const sqrtVal = fpsqrt(val, scale); r = r * scale / (scale + sqrtVal); halvings++; } let sum = r; let term = r; const r2 = r * r; const scale2 = scale * scale; for (let n = 3; ; n += 2) { term = term * r2 / scale2; if (term === 0n) break; if (n % 4 === 3) { sum -= term / BigInt(n); } else { sum += term / BigInt(n); } } for (let i = 0; i < halvings; i++) { sum = 2n * sum; } return sum; } // src/big-decimal/big-decimal.ts var NAN_CMP = NaN; var BigDecimal = class _BigDecimal { /** Working precision (significant digits) for inexact operations like division. */ static precision = 50; // ---------- Static constants ---------- static ZERO = Object.freeze( Object.assign(Object.create(_BigDecimal.prototype), { significand: 0n, exponent: 0 }) ); static ONE = Object.freeze( Object.assign(Object.create(_BigDecimal.prototype), { significand: 1n, exponent: 0 }) ); static TWO = Object.freeze( Object.assign(Object.create(_BigDecimal.prototype), { significand: 2n, exponent: 0 }) ); static NEGATIVE_ONE = Object.freeze( Object.assign(Object.create(_BigDecimal.prototype), { significand: -1n, exponent: 0 }) ); static HALF = Object.freeze( Object.assign(Object.create(_BigDecimal.prototype), { significand: 5n, exponent: -1 }) ); static NAN = Object.freeze( Object.assign(Object.create(_BigDecimal.prototype), { significand: 0n, exponent: NaN }) ); static POSITIVE_INFINITY = Object.freeze( Object.assign(Object.create(_BigDecimal.prototype), { significand: 1n, exponent: Infinity }) ); static NEGATIVE_INFINITY = Object.freeze( Object.assign(Object.create(_BigDecimal.prototype), { significand: -1n, exponent: Infinity }) ); /** Full-precision PI (1100+ digits) */ static _piFullPrecision = null; /** PI rounded to working precision */ static _piCache = null; static _piCachePrecision = 0; /** PI to current working precision. */ static get PI() { if (_BigDecimal._piFullPrecision === null) { _BigDecimal._piFullPrecision = new _BigDecimal( PI_DIGITS[0] + "." + PI_DIGITS.slice(1) ); } const prec = _BigDecimal.precision; if (_BigDecimal._piCache === null || _BigDecimal._piCachePrecision !== prec) { _BigDecimal._piCache = _BigDecimal._piFullPrecision.toPrecision(prec + 4); _BigDecimal._piCachePrecision = prec; } return _BigDecimal._piCache; } significand; exponent; constructor(value) { if (value instanceof _BigDecimal) { this.significand = value.significand; this.exponent = value.exponent; return; } if (typeof value === "bigint") { [this.significand, this.exponent] = normalize(value, 0); return; } if (typeof value === "number") { [this.significand, this.exponent] = fromNumber(value); return; } [this.significand, this.exponent] = fromString(value); } // ---------- State checks ---------- /** True when this value represents NaN. */ isNaN() { return Number.isNaN(this.exponent); } /** True when significand is 0 and the value is not NaN. */ isZero() { return this.exponent === 0 && this.significand === 0n; } /** True when the exponent is finite (not NaN, not +/-Infinity). */ isFinite() { return Number.isFinite(this.exponent); } /** True when the value represents a mathematical integer (exponent >= 0) and is finite. */ isInteger() { return this.isFinite() && this.exponent >= 0; } /** True when significand > 0 (including positive infinity). */ isPositive() { return this.significand > 0n; } /** True when significand < 0 (including negative infinity). */ isNegative() { return this.significand < 0n; } // ---------- Comparison methods ---------- /** * Compare this value with another. * Returns -1 if this < other, 0 if equal, 1 if this > other, NaN if either is NaN. */ cmp(other) { if (typeof other === "number") { if (Number.isNaN(other)) return NAN_CMP; const thisExp2 = this.exponent; if (Number.isNaN(thisExp2)) return NAN_CMP; if (other === 0) { if (this.significand === 0n) return 0; return this.significand > 0n ? 1 : -1; } if (!Number.isFinite(thisExp2)) { if (other === Infinity) return this.significand > 0n ? 0 : -1; if (other === -Infinity) return this.significand < 0n ? 0 : 1; return this.significand > 0n ? 1 : -1; } if (this.significand === 0n) return other > 0 ? -1 : 1; if (other === Infinity) return -1; if (other === -Infinity) return 1; if (this.significand > 0n !== other > 0) return this.significand > 0n ? 1 : -1; if (Number.isInteger(other) && thisExp2 >= 0 && thisExp2 <= 15) { const thisVal = this.significand * pow10(thisExp2); const otherVal = BigInt(other); if (thisVal < otherVal) return -1; if (thisVal > otherVal) return 1; return 0; } other = new _BigDecimal(other); } const thisExp = this.exponent; const otherExp = other.exponent; const thisSig = this.significand; const otherSig = other.significand; if (thisExp !== thisExp || otherExp !== otherExp) return NAN_CMP; if (!Number.isFinite(thisExp) || !Number.isFinite(otherExp)) { if (!Number.isFinite(thisExp) && !Number.isFinite(otherExp)) { if (thisSig === otherSig) return 0; return thisSig > otherSig ? 1 : -1; } if (!Number.isFinite(thisExp)) return thisSig > 0n ? 1 : -1; return otherSig > 0n ? -1 : 1; } if (thisSig === 0n) { if (otherSig === 0n) return 0; return otherSig > 0n ? -1 : 1; } if (otherSig === 0n) return thisSig > 0n ? 1 : -1; if (thisSig > 0n && otherSig < 0n) return 1; if (thisSig < 0n && otherSig > 0n) return -1; if (thisExp === otherExp) { if (thisSig < otherSig) return -1; if (thisSig > otherSig) return 1; return 0; } const thisDigits = bigintDigits(thisSig); const otherDigits = bigintDigits(otherSig); const thisMag = thisDigits + thisExp; const otherMag = otherDigits + otherExp; if (thisMag !== otherMag) { const sign2 = thisSig > 0n ? 1 : -1; return thisMag > otherMag ? sign2 : -sign2; } let aSig = thisSig; let bSig = otherSig; const diff = Math.abs(thisExp - otherExp); if (diff > 1e3) { const aDigits = thisDigits; const bDigits = otherDigits; const target = Math.max(aDigits, bDigits) + 1; if (aDigits < target) aSig = aSig * pow10(target - aDigits); if (bDigits < target) bSig = bSig * pow10(target - bDigits); } else if (thisExp < otherExp) { bSig = bSig * pow10(diff); } else { aSig = aSig * pow10(diff); } if (aSig < bSig) return -1; if (aSig > bSig) return 1; return 0; } /** * Returns true if this value equals other. * NaN === NaN → false (standard NaN semantics). */ eq(other) { if (typeof other === "number") { if (other === 0) return this.significand === 0n && this.exponent === 0; if (other === 1) return this.significand === 1n && this.exponent === 0; if (other === -1) return this.significand === -1n && this.exponent === 0; if (Number.isInteger(other) && Number.isFinite(this.exponent) && this.exponent >= 0 && this.exponent <= 15) { return this.significand * pow10(this.exponent) === BigInt(other); } return this.cmp(other) === 0; } return this.significand === other.significand && this.exponent === other.exponent; } /** Returns true if this value is strictly less than other. */ lt(other) { return this.cmp(other) === -1; } /** Returns true if this value is less than or equal to other. */ lte(other) { const c = this.cmp(other); return c === -1 || c === 0; } /** Returns true if this value is strictly greater than other. */ gt(other) { return this.cmp(other) === 1; } /** Returns true if this value is greater than or equal to other. */ gte(other) { const c = this.cmp(other); return c === 1 || c === 0; } // ---------- Arithmetic methods ---------- /** * Add this value to another. * Aligns exponents, adds significands. The result is exact. */ add(other) { if (typeof other === "number") other = new _BigDecimal(other); const thisExp = this.exponent; const otherExp = other.exponent; if (Number.isFinite(thisExp) && Number.isFinite(otherExp)) { if (thisExp === otherExp) return fromRaw(this.significand + other.significand, thisExp); const diff = thisExp - otherExp; if (diff > 0) return fromRaw( this.significand * pow10(diff) + other.significand, otherExp ); return fromRaw( this.significand + other.significand * pow10(-diff), thisExp ); } if (thisExp !== thisExp || otherExp !== otherExp) return _BigDecimal.NAN; const thisInf = !Number.isFinite(thisExp); const otherInf = !Number.isFinite(otherExp); if (thisInf && otherInf) { if (this.significand !== other.significand) return _BigDecimal.NAN; return this.significand > 0n ? _BigDecimal.POSITIVE_INFINITY : _BigDecimal.NEGATIVE_INFINITY; } if (thisInf) return this.significand > 0n ? _BigDecimal.POSITIVE_INFINITY : _BigDecimal.NEGATIVE_INFINITY; return other.significand > 0n ? _BigDecimal.POSITIVE_INFINITY : _BigDecimal.NEGATIVE_INFINITY; } /** * Subtract other from this. * Aligns exponents, subtracts significands. The result is exact. */ sub(other) { if (typeof other === "number") other = new _BigDecimal(other); const thisExp = this.exponent; const otherExp = other.exponent; if (Number.isFinite(thisExp) && Number.isFinite(otherExp)) { if (thisExp === otherExp) return fromRaw(this.significand - other.significand, thisExp); const diff = thisExp - otherExp; if (diff > 0) return fromRaw( this.significand * pow10(diff) - other.significand, otherExp ); return fromRaw( this.significand - other.significand * pow10(-diff), thisExp ); } if (thisExp !== thisExp || otherExp !== otherExp) return _BigDecimal.NAN; const thisInf = !Number.isFinite(thisExp); const otherInf = !Number.isFinite(otherExp); if (thisInf && otherInf) { if (this.significand === other.significand) return _BigDecimal.NAN; return this.significand > 0n ? _BigDecimal.POSITIVE_INFINITY : _BigDecimal.NEGATIVE_INFINITY; } if (thisInf) return this.significand > 0n ? _BigDecimal.POSITIVE_INFINITY : _BigDecimal.NEGATIVE_INFINITY; return other.significand > 0n ? _BigDecimal.NEGATIVE_INFINITY : _BigDecimal.POSITIVE_INFINITY; } /** * Multiply this value by another. * Multiplies significands, adds exponents. The result is exact. */ mul(other) { if (typeof other === "number") other = new _BigDecimal(other); const thisExp = this.exponent; const otherExp = other.exponent; if (Number.isFinite(thisExp) && Number.isFinite(otherExp)) return fromRaw(this.significand * other.significand, thisExp + otherExp); if (thisExp !== thisExp || otherExp !== otherExp) return _BigDecimal.NAN; if (this.significand === 0n || other.significand === 0n) return _BigDecimal.NAN; const signA = this.significand > 0n ? 1n : -1n; const signB = other.significand > 0n ? 1n : -1n; return signA * signB > 0n ? _BigDecimal.POSITIVE_INFINITY : _BigDecimal.NEGATIVE_INFINITY; } /** * Negate this value. Zero.neg() → Zero. */ neg() { const sig = this.significand; if (sig === 0n) return this; if (Number.isFinite(this.exponent)) return fromRaw(-sig, this.exponent); return sig > 0n ? _BigDecimal.NEGATIVE_INFINITY : _BigDecimal.POSITIVE_INFINITY; } /** * Absolute value. If already non-negative, returns this. */ abs() { if (this.significand >= 0n) return this; if (!Number.isFinite(this.exponent)) return _BigDecimal.POSITIVE_INFINITY; return fromRaw(-this.significand, this.exponent); } /** * Round toward -Infinity. * `3.7` → `3`, `-3.7` → `-4`. * For integers returns this. NaN/Infinity → return this. */ floor() { const exp3 = this.exponent; if (exp3 >= 0) return this; if (Number.isFinite(exp3)) { const t = this.trunc(); if (this.significand < 0n) return t.sub(fromRaw(1n, 0)); return t; } return this; } /** * Round toward +Infinity. * `3.2` → `4`, `-3.2` → `-3`. * For integers returns this. NaN/Infinity → return this. */ ceil() { const exp3 = this.exponent; if (exp3 >= 0) return this; if (Number.isFinite(exp3)) { const t = this.trunc(); if (this.significand > 0n) return t.add(fromRaw(1n, 0)); return t; } return this; } /** * Round half away from zero (standard math rounding). * `3.5` → `4`, `-3.5` → `-4`, `3.4` → `3`, `3.6` → `4`. * For integers returns this. NaN/Infinity → return this. */ round() { const exp3 = this.exponent; if (exp3 >= 0) return this; if (Number.isFinite(exp3)) { const half = fromRaw(5n, -1); if (this.significand > 0n) return this.add(half).trunc(); return this.sub(half).trunc(); } return this; } /** * Truncate toward zero, removing the fractional part. * For integers (exponent >= 0) returns this. * NaN → NaN, +/-Infinity → +/-Infinity. */ trunc() { const exp3 = this.exponent; if (exp3 >= 0) return this; if (Number.isFinite(exp3)) { const truncSig = this.significand / pow10(-exp3); if (truncSig === 0n) return fromRaw(0n, 0); return fromRaw(truncSig, 0); } return this; } /** * Divide this value by another. * Uses `BigDecimal.precision` to determine significant digits for inexact results. * * Special cases: * - NaN / x → NaN, x / NaN → NaN * - nonzero / 0 → +/-Infinity (matching Decimal.js behavior) * - 0 / 0 → NaN * - Inf / finite → Inf (correct sign) * - finite / Inf → 0 * - Inf / Inf → NaN */ div(other) { if (typeof other === "number") other = new _BigDecimal(other); const thisExp = this.exponent; const otherExp = other.exponent; const thisSig = this.significand; const otherSig = other.significand; if (Number.isFinite(thisExp) && Number.isFinite(otherExp)) { if (otherSig === 0n) { if (thisSig === 0n) return _BigDecimal.NAN; return thisSig > 0n ? _BigDecimal.POSITIVE_INFINITY : _BigDecimal.NEGATIVE_INFINITY; } if (thisSig === 0n) return fromRaw(0n, 0); const prec = _BigDecimal.precision; const guard = 10; const absDividend = thisSig < 0n ? -thisSig : thisSig; const absDivisor = otherSig < 0n ? -otherSig : otherSig; const dividendDigits = bigintDigits(absDividend); const divisorDigits = bigintDigits(absDivisor); const totalScale = prec + guard + Math.max(0, divisorDigits - dividendDigits); const scale = pow10(totalScale); const quotient = thisSig * scale / otherSig; const resultExp = thisExp - otherExp - totalScale; return fromRaw(quotient, resultExp).toPrecision(prec); } if (thisExp !== thisExp || otherExp !== otherExp) return _BigDecimal.NAN; const thisInf = !Number.isFinite(thisExp); const otherInf = !Number.isFinite(otherExp); if (thisInf && otherInf) return _BigDecimal.NAN; if (thisInf) { const signA = thisSig > 0n ? 1n : -1n; const signB = otherSig > 0n ? 1n : otherSig < 0n ? -1n : 1n; return signA * signB > 0n ? _BigDecimal.POSITIVE_INFINITY : _BigDecimal.NEGATIVE_INFINITY; } return fromRaw(0n, 0); } /** * Multiplicative inverse: 1 / this. * Uses `BigDecimal.precision` for the division. */ inv() { return fromRaw(1n, 0).div(this); } /** * Modulo (remainder after truncating division). * Defined as: this - trunc(this / other) * other * * The sign of the result matches the sign of the dividend (this), * consistent with JavaScript's % operator and Decimal.js. */ mod(other) { if (typeof other === "number") other = new _BigDecimal(other); const thisExp = this.exponent; const otherExp = other.exponent; if (Number.isFinite(thisExp) && Number.isFinite(otherExp)) { if (other.significand === 0n) return _BigDecimal.NAN; if (this.significand === 0n) return fromRaw(0n, 0); return this.sub(this.div(other).trunc().mul(other)).toPrecision( _BigDecimal.precision ); } if (thisExp !== thisExp || otherExp !== otherExp) return _BigDecimal.NAN; if (!Number.isFinite(thisExp)) return _BigDecimal.NAN; return new _BigDecimal(this); } /** * Raise to a power. * * - Integer exponent: exact result via repeated squaring * - Zero exponent: 1 (for any non-NaN base) * - Negative integer exponent: pow(abs(n)).inv() (uses precision) * - Non-integer exponent on positive base: exp(n * ln(this)) * - Non-integer exponent on negative base: NaN (real-valued result doesn't exist) * * Special cases: * - NaN base or exponent → NaN * - Infinite exponent → NaN * - 0^0 → 1 (mathematical convention) * - 0^positive → 0 * - 0^negative → Infinity */ pow(n) { if (typeof n === "number") n = new _BigDecimal(n); if (this.isNaN() || n.isNaN()) return _BigDecimal.NAN; if (!n.isFinite()) return _BigDecimal.NAN; if (n.isInteger()) { const expValue = n.toBigInt(); if (expValue === 0n) return fromRaw(1n, 0); if (!this.isFinite()) { if (expValue > 0n) { if (this.significand < 0n && expValue % 2n !== 0n) return _BigDecimal.NEGATIVE_INFINITY; return _BigDecimal.POSITIVE_INFINITY; } return fromRaw(0n, 0); } if (this.isZero()) { if (expValue > 0n) return fromRaw(0n, 0); return _BigDecimal.POSITIVE_INFINITY; } if (expValue < 0n) { return this.pow(n.neg()).inv(); } const absSig = this.significand < 0n ? -this.significand : this.significand; const thisLog10 = bigintDigits(absSig) + this.exponent; const resultLog10 = Number(expValue) * thisLog10; if (resultLog10 > 9e15) { return this.significand < 0n && expValue % 2n !== 0n ? _BigDecimal.NEGATIVE_INFINITY : _BigDecimal.POSITIVE_INFINITY; } if (resultLog10 < -9e15) { return fromRaw(0n, 0); } const prec = _BigDecimal.precision; let result = fromRaw(1n, 0); let base = this; let exp3 = expValue; while (exp3 > 0n) { if (exp3 & 1n) { result = result.mul(base).toPrecision(prec); } exp3 >>= 1n; if (exp3 > 0n) { base = base.mul(base).toPrecision(prec); } } return result; } if (!this.isFinite()) { if (this.significand < 0n) return _BigDecimal.NAN; if (n.significand > 0n) return _BigDecimal.POSITIVE_INFINITY; return _BigDecimal.ZERO; } if (this.isZero()) { if (n.significand > 0n) return _BigDecimal.ZERO; return _BigDecimal.POSITIVE_INFINITY; } if (this.s