UNPKG

@mathigon/fermat

Version:

Powerful mathematics and statistics library for JavaScript.

1,168 lines (1,156 loc) 35.7 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod2) => __copyProps(__defProp({}, "__esModule", { value: true }), mod2); // src/index.ts var index_exports = {}; __export(index_exports, { Complex: () => Complex, Matrix: () => matrix_exports, Random: () => random_exports, Regression: () => regression_exports, Vector: () => Vector, XNumber: () => XNumber, binomial: () => binomial, clamp: () => clamp, correlation: () => correlation, covariance: () => covariance, cube: () => cube, digits: () => digits, eulerPhi: () => eulerPhi, factorial: () => factorial, gcd: () => gcd, generatePrime: () => generatePrime, goldbach: () => goldbach, isBetween: () => isBetween, isInteger: () => isInteger, isPrime: () => isPrime, lcm: () => lcm, lerp: () => lerp, listPrimes: () => listPrimes, log: () => log, mean: () => mean, median: () => median, mod: () => mod, mode: () => mode, nearlyEquals: () => nearlyEquals, numberFormat: () => numberFormat, parseNumber: () => parseNumber, permutations: () => permutations, polynomial: () => polynomial, primeFactorisation: () => primeFactorisation, primeFactors: () => primeFactors, quadratic: () => quadratic, quantile: () => quantile, round: () => round, roundTo: () => roundTo, scientificFormat: () => scientificFormat, sign: () => sign, square: () => square, stdDev: () => stdDev, subsets: () => subsets, toOrdinal: () => toOrdinal, toWord: () => toWord, variance: () => variance }); module.exports = __toCommonJS(index_exports); // src/arithmetic.ts var PRECISION = 1e-6; function nearlyEquals(a, b, t = PRECISION) { if (isNaN(a) || isNaN(b)) return false; return Math.abs(a - b) < t; } function isInteger(x, t = PRECISION) { return nearlyEquals(x, Math.round(x), t); } function isBetween(value, a, b, t = PRECISION) { if (a > b) [a, b] = [b, a]; return value > a + t && value < b - t; } function sign(value, t = PRECISION) { return nearlyEquals(value, 0, t) ? 0 : value > 0 ? 1 : -1; } var NUM_REGEX = /(\d+)(\d{3})/; var POWER_SUFFIX = ["", "k", "m", "b", "t", "q"]; function addThousandSeparators(x) { let [n, dec] = x.split("."); while (NUM_REGEX.test(n)) { n = n.replace(NUM_REGEX, "$1,$2"); } return n + (dec ? `.${dec}` : ""); } function addPowerSuffix(n, places = 6) { if (!places) return `${n}`; const digits2 = `${Math.abs(Math.floor(n))}`.length; const chars = digits2 + (n < 0 ? 1 : 0); if (chars <= places) return `${round(n, places - chars)}`; const x = Math.floor(Math.log10(Math.abs(n)) / 3); const suffix = POWER_SUFFIX[x]; const decimalPlaces = places - (digits2 % 3 || 3) - (suffix ? 1 : 0) - (n < 0 ? 1 : 0); return round(n / Math.pow(10, 3 * x), decimalPlaces) + suffix; } function numberFormat(n, places = 0, separators = true) { const str = addPowerSuffix(n, places).replace("-", "\u2013"); return separators ? addThousandSeparators(str) : str; } function scientificFormat(value, places = 6) { const abs = Math.abs(value); if (isBetween(abs, Math.pow(10, -places), Math.pow(10, places))) { return numberFormat(value, places); } if (abs > Number.MAX_VALUE) return `${Math.sign(value) < 0 ? "\u2013" : ""}\u221E`; if (abs < Number.MIN_VALUE) return "0"; const [str, exponent] = value.toExponential().split("e"); const top = exponent.replace("+", "").replace("-", "\u2013"); const isNegative = top.startsWith("\u2013"); return `${str.slice(0, 5)} \xD7 10^${(isNegative ? "(" : "") + top + (isNegative ? ")" : "")}`; } var SPECIAL_DECIMAL = /^-?0,[0-9]+$/; var POINT_DECIMAL = /^-?([0-9]+(,[0-9]{3})*)?\.?[0-9]*$/; var COMMA_DECIMAL = /^-?[0-9]+(\.[0-9]{3})*,?[0-9]*$/; function parseNumber(str) { str = str.replace(/^–/, "-").trim(); if (!str || str.match(/[^0-9.,-]/)) return NaN; if (SPECIAL_DECIMAL.test(str)) { return parseFloat(str.replace(/,/, ".")); } if (POINT_DECIMAL.test(str)) { return parseFloat(str.replace(/,/g, "")); } if (COMMA_DECIMAL.test(str)) { return parseFloat(str.replace(/\./g, "").replace(/,/, ".")); } return NaN; } function toOrdinal(x) { if (Math.abs(x) % 100 >= 11 && Math.abs(x) % 100 <= 13) { return `${x}th`; } switch (x % 10) { case 1: return `${x}st`; case 2: return `${x}nd`; case 3: return `${x}rd`; default: return `${x}th`; } } var ONES = [ "", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" ]; var TENS = [ "", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" ]; var MULTIPLIERS = [ "", " thousand", " million", " billion", " trillion", " quadrillion", " quintillion", " sextillion" ]; function toWordSingle(number) { const [h, t, o] = number.split(""); const hundreds = h === "0" ? "" : ` ${ONES[+h]} hundred`; if (t + o === "00") return hundreds; if (+t < 2) return `${hundreds} ${ONES[+(t + o)]}`; if (o === "0") return `${hundreds} ${TENS[+t]}`; return `${hundreds} ${TENS[+t]}-${ONES[+o]}`; } function toWord(n) { if (n === 0) return "zero"; const str = Math.round(Math.abs(n)).toString(); const chunks = Math.ceil(str.length / 3); const padded = str.padStart(3 * chunks, "0"); let result = ""; for (let i = 0; i < chunks; i += 1) { const chunk = padded.substr(i * 3, 3); if (chunk === "000") continue; result += toWordSingle(chunk) + MULTIPLIERS[chunks - 1 - i]; } return result.trim(); } function digits(n) { const str = `${Math.abs(n)}`; return str.split("").reverse().map((x) => +x); } function round(n, precision = 0) { const factor = Math.pow(10, precision); return Math.round(n * factor) / factor; } function roundTo(n, increment = 1) { return Math.round(n / increment) * increment; } function clamp(x, min = -Infinity, max = Infinity) { return Math.min(max, Math.max(min, x)); } function lerp(a, b, t = 0.5) { return a + (b - a) * t; } function square(x) { return x * x; } function cube(x) { return x * x * x; } function mod(a, m) { return (a % m + m) % m; } function log(x, b) { return b === void 0 ? Math.log(x) : Math.log(x) / Math.log(b); } function quadratic(a, b, c) { if (nearlyEquals(a, 0) && nearlyEquals(b, 0)) return []; if (nearlyEquals(a, 0)) return [-c / b]; const p = -b / 2 / a; const q = Math.sqrt(b * b - 4 * a * c) / 2 / a; return [p + q, p - q]; } function polynomial(x, coefficients) { let total4 = 0; let xi = 1; for (const c of coefficients) { total4 += xi * c; xi *= x; } return total4; } // src/combinatorics.ts function factorial(x) { if (x === 0) return 1; if (x < 0) return NaN; let n = 1; for (let i = 2; i <= x; ++i) n *= i; return n; } function binomial(n, k) { if (k < 0 || k > n) return 0; if (k === 0) return 1; if (2 * k > n) return binomial(n, n - k); let coeff = 1; for (let i = 1; i <= k; ++i) coeff *= (n - i + 1) / i; return Math.round(coeff); } function permutations(arr) { const permArr = []; const usedChars = []; permuteHelper(arr, permArr, usedChars); return permArr; } function permuteHelper(input, permArr, usedChars) { for (let i = 0; i < input.length; i++) { const term = input.splice(i, 1)[0]; usedChars.push(term); if (input.length === 0) { permArr.push(usedChars.slice()); } permuteHelper(input, permArr, usedChars); input.splice(i, 0, term); usedChars.pop(); } } function subsets(array, length = 0) { const copy = array.slice(0); const results = subsetsHelper(copy); return length ? results.filter((x) => x.length === length) : results; } function subsetsHelper(array) { if (array.length === 1) return [[], array]; const last = array.pop(); const subsets2 = subsetsHelper(array); const result = []; for (const s of subsets2) { result.push(s, [...s, last]); } return result; } // src/complex.ts var absStr = (n, suffix) => { const prefix = n < 0 ? "\u2013" : ""; if (Math.abs(n) === 1 && suffix) return prefix + suffix; return prefix + Math.abs(n) + (suffix || ""); }; var Complex = class _Complex { constructor(re = 0, im = 0) { this.re = re; this.im = im; } get modulus() { return Math.sqrt(this.re * this.re + this.im * this.im); } get argument() { return Math.atan2(this.im, this.re); } get conjugate() { return new _Complex(this.re, -this.im); } /** Returns the ith nth-root of this complex number. */ root(n, i = 0) { const r = Math.pow(this.modulus, 1 / n); const th = (this.argument + i * 2 * Math.PI) / n; return new _Complex(r * Math.cos(th), r * Math.sin(th)); } toString(precision = 2) { const re = round(this.re, precision); const im = round(this.im, precision); if (im === 0) return absStr(re); if (re === 0) return absStr(im, "i"); return [absStr(re), im < 0 ? "\u2013" : "+", absStr(Math.abs(im), "i")].join(" "); } // --------------------------------------------------------------------------- add(a) { return _Complex.sum(this, a); } subtract(a) { return _Complex.difference(this, a); } multiply(a) { return _Complex.product(this, a); } divide(a) { return _Complex.quotient(this, a); } /** Calculates the sum of two complex numbers c1 and c2. */ static sum(c1, c2) { if (typeof c1 === "number") c1 = new _Complex(c1, 0); if (typeof c2 === "number") c2 = new _Complex(c2, 0); return new _Complex(c1.re + c2.re, c1.im + c2.im); } /** Calculates the difference of two complex numbers c1 and c2. */ static difference(c1, c2) { if (typeof c1 === "number") c1 = new _Complex(c1, 0); if (typeof c2 === "number") c2 = new _Complex(c2, 0); return new _Complex(c1.re - c2.re, c1.im - c2.im); } /** Calculates the product of two complex numbers c1 and c2. */ static product(c1, c2) { if (typeof c1 === "number") c1 = new _Complex(c1, 0); if (typeof c2 === "number") c2 = new _Complex(c2, 0); const re = c1.re * c2.re - c1.im * c2.im; const im = c1.im * c2.re + c1.re * c2.im; return new _Complex(re, im); } /** Calculates the quotient of two complex numbers c1 and c2. */ static quotient(c1, c2) { if (typeof c1 === "number") c1 = new _Complex(c1, 0); if (typeof c2 === "number") c2 = new _Complex(c2, 0); if (Math.abs(c2.re) < Number.EPSILON || Math.abs(c2.im) < Number.EPSILON) { return new _Complex(Infinity, Infinity); } const denominator = c2.re * c2.re + c2.im * c2.im; const re = (c1.re * c2.re + c1.im * c2.im) / denominator; const im = (c1.im * c2.re - c1.re * c2.im) / denominator; return new _Complex(re, im); } /** Calculates e^c for a complex number c. */ static exp(c) { if (typeof c === "number") c = new _Complex(c, 0); const r = Math.exp(c.re); return new _Complex(r * Math.cos(c.im), r * Math.sin(c.im)); } }; // src/number-theory.ts var import_core = require("@mathigon/core"); function gcd(...numbers) { const [first, ...rest] = numbers; if (rest.length > 1) return gcd(first, gcd(...rest)); let a = Math.abs(first); let b = Math.abs(rest[0]); while (b) [a, b] = [b, a % b]; return a; } function lcm(...numbers) { const [first, ...rest] = numbers; if (rest.length > 1) return lcm(first, lcm(...rest)); return Math.abs(first * rest[0]) / gcd(first, rest[0]); } function isPrime(n) { if (n % 1 !== 0 || n < 2) return false; if (n % 2 === 0) return n === 2; if (n % 3 === 0) return n === 3; const m = Math.sqrt(n); for (let i = 5; i <= m; i += 6) { if (n % i === 0) return false; if (n % (i + 2) === 0) return false; } return true; } function primeFactorisation(n) { if (n === 1) return []; if (isPrime(n)) return [n]; const maxf = Math.sqrt(n); for (let f = 2; f <= maxf; ++f) { if (n % f === 0) { return primeFactorisation(f).concat(primeFactorisation(n / f)); } } return []; } function primeFactors(n) { return (0, import_core.unique)(primeFactorisation(n)); } function listPrimes(n = 100) { if (n < 2) return []; const result = [2]; for (let i = 3; i <= n; i++) { let notMultiple = false; for (const r of result) { notMultiple = notMultiple || 0 === i % r; } if (!notMultiple) result.push(i); } return result; } function generatePrime(d) { if (d < 2 || d > 16) throw new Error("Invalid number of digits."); const lastDigit = [1, 3, 7, 9]; const pow = Math.pow(10, d - 2); while (true) { const n = Math.floor(Math.random() * 9 * pow) + pow; const x = 10 * n + lastDigit[Math.floor(4 * Math.random())]; if (isPrime(x)) return x; } } function goldbach(x) { if (x === 4) return [2, 2]; let a = x / 2; let b = x / 2; if (a % 2 === 0) { a--; b++; } while (a >= 3) { if (isPrime(a) && isPrime(b)) return [a, b]; a -= 2; b += 2; } return [-1, -1]; } function eulerPhi(x) { if (x <= 0) throw Error("Number should be greater than zero"); let n = x; for (const p of primeFactors(x)) n *= (p - 1) / p; return n; } // src/xnumber.ts var FORMAT = /^([0-9\-.]*)([%πkmbtq]?)(\/([0-9\-.]+))?([%π]?)$/; var tooBig = (x) => x >= Number.MAX_SAFE_INTEGER; var XNumber = class _XNumber { /** Only used for fractions and always ≥ 0. */ constructor(num, den, unit) { this.unit = unit; this.num = den !== void 0 && den < 0 ? -num : num; if (den !== void 0 && Math.abs(den) !== 1 && num !== 0) this.den = Math.abs(den); } valueOf() { return this.value; } toMixed() { if (!this.den || this.unit) return this.toString(); const part = Math.abs(this.num) % this.den; const whole = Math.abs(Math.trunc(this.value)); if (!whole) return this.toString(); return `${this.sign < 0 ? "\u2013" : ""}${whole} ${part}/${this.den}`; } toExpr(type, precision = 4) { const v = this.value; if (Math.abs(v) >= Number.MAX_VALUE) return "\u221E"; if (tooBig(this.num) || this.den && tooBig(this.den)) type = "decimal"; if (type === "scientific" || Math.abs(v) >= Number.MAX_SAFE_INTEGER) { const [base, power2] = this.value.toExponential(precision - 1).split("e"); if (Math.abs(+power2) >= precision) { const isNeg = power2.startsWith("-"); const exp = `${isNeg ? "(" : ""}${isNeg ? power2 : power2.slice(1)}${isNeg ? ")" : ""}`; return `${base.replace(/\.?0+$/, "")} \xD7 10^${exp}${this.unit || ""}`; } } if (!this.unit && !this.den || type === "decimal" || type === "scientific") { const formatted = numberFormat(this.value, precision); return formatted.match(/^[\d.]+$/g) ? formatted : `"${formatted}"`; } else { return type === "mixed" ? this.toMixed() : this.toString(); } } toString(precision = 4) { const separators = !this.den && !this.unit; let num = numberFormat(this.num, this.den ? 0 : precision, separators); let unit = this.unit || ""; const den = this.den ? `/${numberFormat(this.den, 0, separators)}` : ""; if (num === "0") unit = ""; if (unit === "\u03C0" && !this.den && (num === "1" || num === "\u20131")) num = num.replace("1", ""); return `${num}${den}${unit}`; } toMathML() { let str = `<mn>${this.num}</mn>`; if (this.den !== void 0) str = `<mfrac>${str}<mn>${this.den}</mn></mfrac>`; if (this.unit) str += this.unit === "\u03C0" ? `<mi>\u03C0</mi>` : `<mo>%</mo>`; return str; } // --------------------------------------------------------------------------- /** * Returns the value of this number as a decimal. For example, 2/5 and 40% * would both return 0.4. */ get value() { const unit = this.unit === "%" ? 1 / 100 : this.unit === "\u03C0" ? Math.PI : 1; return this.num * unit / (this.den || 1); } get sign() { return Math.sign(this.num); } /** Simplifies fractions, e.g. 4/8 would become 1/2. */ get simplified() { if (!this.den) return this; const factor = gcd(Math.abs(this.num), this.den); return new _XNumber(this.num / factor, this.den / factor, this.unit); } /** Returns 1/x of this number. */ get inverse() { if (!this.den) return new _XNumber(this.den, this.num); return new _XNumber(1 / this.num, void 0, this.unit); } /** Returns -x of this number. */ get negative() { return new _XNumber(-this.num, this.den, this.unit); } get fraction() { if (this.unit || !isInteger(this.num)) return; return [this.num, this.den || 1]; } // --------------------------------------------------------------------------- /** Parses a number string, e.g. '1/2' or '20.7%'. */ static fromString(s) { s = s.toLowerCase().replace(/[\s,"]/g, "").replace("\u2013", "-").replace("pi", "\u03C0"); const match = s.match(FORMAT); if (!match) return; let suffix = match[2] || match[5] || void 0; let num = match[1] ? +match[1] : void 0; const den = match[4] ? +match[4] : void 0; if (suffix === "\u03C0" && (!match[1] || match[1] === "-")) num = match[1] ? -1 : 1; if (num === void 0 || isNaN(num)) return; const power2 = suffix ? "kmbtq".indexOf(suffix) : -1; if (power2 >= 0) { num *= 1e3 ** (power2 + 1); suffix = void 0; } if (den === void 0) return new _XNumber(num, void 0, suffix); if (isNaN(den) || nearlyEquals(den, 0)) return; if (!isInteger(num) || !isInteger(den)) return new _XNumber(num / den, void 0, suffix); return new _XNumber(num, den, suffix); } /** Converts a decimal into the closest fraction with a given maximum denominator. */ static fractionFromDecimal(x, maxDen = 1e3, precision = 1e-12) { let n = [1, 0]; let d = [0, 1]; const absX = Math.abs(x); let rem = absX; while (Math.abs(n[0] / d[0] - absX) > precision) { const a = Math.floor(rem); n = [a * n[0] + n[1], n[0]]; d = [a * d[0] + d[1], d[0]]; if (d[0] > maxDen) return new _XNumber(x); rem = 1 / (rem - a); } if (!nearlyEquals(n[0] / d[0], absX, precision)) return new _XNumber(x); return new _XNumber(sign(x) * n[0], d[0] === 1 ? void 0 : d[0]); } // --------------------------------------------------------------------------- clamp(min, max) { const v = this.value; if (min !== void 0 && v < min) return new _XNumber(min); if (max !== void 0 && v > max) return new _XNumber(max); return this; } add(a) { return _XNumber.sum(this, a); } subtract(a) { return _XNumber.difference(this, a); } multiply(a) { return _XNumber.product(this, a); } divide(a) { return _XNumber.quotient(this, a); } /** Calculates the sum of two fractions a and b. */ static sum(a, b) { if (typeof b === "number") b = new _XNumber(b); if (a.num === 0) return b; if (a.unit !== b.unit) return new _XNumber(a.value + b.value); if (!a.den && !b.den) return new _XNumber(a.num + b.num, void 0, a.unit); if (!a.den) [a, b] = [b, a]; if (!isInteger(b.num)) return new _XNumber(a.value + b.value, void 0, a.unit); const common = lcm(a.den, b.den || 1); const fa = common / a.den; const fb = common / (b.den || 1); return new _XNumber(a.num * fa + b.num * fb, common, a.unit); } /** Calculates the difference of two numbers a and b. */ static difference(a, b) { if (typeof b === "number") b = new _XNumber(b); return _XNumber.sum(a, b.negative); } /** Calculates the product of two numbers a and b. */ static product(a, b) { if (typeof b === "number") b = new _XNumber(b); if (!a.unit && !a.den && isInteger(a.num)) return new _XNumber(a.num * b.num, b.den, b.unit); if (!b.unit && !b.den && isInteger(b.num)) return new _XNumber(a.num * b.num, a.den, a.unit); if (a.unit === "\u03C0" || b.unit === "\u03C0" || !isInteger(a.num) || !isInteger(b.num)) return new _XNumber(a.value * b.value); const units = (a.unit === "%" ? 100 : 1) * (b.unit === "%" ? 100 : 1); return new _XNumber(a.num * b.num, (a.den || 1) * (b.den || 1) * units); } /** Calculates the quotient of two fractions a and b. */ static quotient(a, b) { if (typeof b === "number") b = new _XNumber(b); return _XNumber.product(a, b.inverse); } }; // src/matrix.ts var matrix_exports = {}; __export(matrix_exports, { determinant: () => determinant, fill: () => fill, identity: () => identity, inverse: () => inverse, product: () => product, reflection: () => reflection, rotation: () => rotation, scalarProduct: () => scalarProduct, shear: () => shear, sum: () => sum, transpose: () => transpose }); var import_core2 = require("@mathigon/core"); function fill(value, x, y) { return (0, import_core2.repeat2D)(value, x, y); } function identity(n = 2) { const x = fill(0, n, n); for (let i = 0; i < n; ++i) x[i][i] = 1; return x; } function rotation(angle) { const sin = Math.sin(angle); const cos = Math.cos(angle); return [[cos, -sin], [sin, cos]]; } function shear(lambda) { return [[1, lambda], [0, 1]]; } function reflection(angle) { const sin = Math.sin(2 * angle); const cos = Math.cos(2 * angle); return [[cos, sin], [sin, -cos]]; } function sum(...matrices) { const [M1, ...rest] = matrices; const M2 = rest.length > 1 ? sum(...rest) : rest[0]; if (M1.length !== M2.length || M1[0].length !== M2[0].length) { throw new Error("Matrix sizes don\u2019t match"); } const S = []; for (let i = 0; i < M1.length; ++i) { const row = []; for (let j = 0; j < M1[i].length; ++j) { row.push(M1[i][j] + M2[i][j]); } S.push(row); } return S; } function scalarProduct(M, v) { return M.map((row) => row.map((x) => x * v)); } function product(...matrices) { const [M1, ...rest] = matrices; const M2 = rest.length > 1 ? product(...rest) : rest[0]; if (M1[0].length !== M2.length) { throw new Error("Matrix sizes don\u2019t match."); } const P2 = []; for (let i = 0; i < M1.length; ++i) { const row = []; for (let j = 0; j < M2[0].length; ++j) { let value = 0; for (let k = 0; k < M2.length; ++k) { value += M1[i][k] * M2[k][j]; } row.push(value); } P2.push(row); } return P2; } function transpose(M) { const T = []; for (let j = 0; j < M[0].length; ++j) { const row = []; for (let i = 0; i < M.length; ++i) { row.push(M[i][j]); } T.push(row); } return T; } function determinant(M) { if (M.length !== M[0].length) throw new Error("Not a square matrix."); const n = M.length; if (n === 1) return M[0][0]; if (n === 2) return M[0][0] * M[1][1] - M[0][1] * M[1][0]; let det = 0; for (let j = 0; j < n; ++j) { let diagLeft = M[0][j]; let diagRight = M[0][j]; for (let i = 1; i < n; ++i) { diagRight *= M[i][(j + i) % n]; diagLeft *= M[i][(j - i + n) % n]; } det += diagRight - diagLeft; } return det; } function inverse(M) { const n = M.length; if (n !== M[0].length) throw new Error("Not a square matrix."); const I = identity(n); const C = (0, import_core2.tabulate2D)((x, y) => M[x][y], n, n); for (let i = 0; i < n; ++i) { let e = C[i][i]; if (nearlyEquals(e, 0)) { for (let ii = i + 1; ii < n; ++ii) { if (C[ii][i] !== 0) { for (let j = 0; j < n; ++j) { [C[ii][j], C[i][j]] = [C[i][j], C[ii][j]]; [I[ii][j], I[i][j]] = [I[i][j], I[ii][j]]; } break; } } e = C[i][i]; if (nearlyEquals(e, 0)) throw new Error("Matrix not invertible."); } for (let j = 0; j < n; ++j) { C[i][j] = C[i][j] / e; I[i][j] = I[i][j] / e; } for (let ii = 0; ii < n; ++ii) { if (ii === i) continue; const f = C[ii][i]; for (let j = 0; j < n; ++j) { C[ii][j] -= f * C[i][j]; I[ii][j] -= f * I[i][j]; } } } return I; } // src/random.ts var random_exports = {}; __export(random_exports, { bernoulli: () => bernoulli, binomial: () => binomial2, cauchy: () => cauchy, chiCDF: () => chiCDF, exponential: () => exponential, find: () => find, geometric: () => geometric, integer: () => integer, integrate: () => integrate, normal: () => normal, normalPDF: () => normalPDF, poisson: () => poisson, shuffle: () => shuffle, smart: () => smart, uniform: () => uniform, weighted: () => weighted }); var import_core3 = require("@mathigon/core"); function shuffle(a) { a = a.slice(0); for (let i = a.length - 1; i > 0; --i) { const j = Math.floor(Math.random() * (i + 1)); [a[i], a[j]] = [a[j], a[i]]; } return a; } function integer(a, b) { const start = b === void 0 ? 0 : a; const length = b === void 0 ? a : b - a + 1; return start + Math.floor(length * Math.random()); } function weighted(weights) { const x = Math.random() * (0, import_core3.total)(weights); let cum = 0; return weights.findIndex((w) => (cum += w) >= x); } function find(items) { return items[Math.floor(items.length * Math.random())]; } var SMART_RANDOM_CACHE = /* @__PURE__ */ new Map(); function smart(n, id) { if (!id) id = (0, import_core3.uid)(); if (!SMART_RANDOM_CACHE.has(id)) SMART_RANDOM_CACHE.set(id, (0, import_core3.repeat)(1, n)); const cache = SMART_RANDOM_CACHE.get(id); const x = weighted(cache.map((x2) => x2 * x2)); cache[x] -= 1; if (cache[x] <= 0) SMART_RANDOM_CACHE.set(id, cache.map((x2) => x2 + 1)); return x; } function bernoulli(p = 0.5) { return Math.random() < p ? 1 : 0; } function binomial2(n = 1, p = 0.5) { let t = 0; for (let i = 0; i < n; ++i) t += bernoulli(p); return t; } function poisson(l = 1) { if (l <= 0) return 0; const L = Math.exp(-l); let p = 1; let k = 0; for (; p > L; ++k) p *= Math.random(); return k - 1; } function uniform(a = 0, b = 1) { return a + (b - a) * Math.random(); } function normal(m = 0, v = 1) { const u1 = Math.random(); const u2 = Math.random(); const rand = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2); return rand * Math.sqrt(v) + m; } function exponential(l = 1) { return l <= 0 ? 0 : -Math.log(Math.random()) / l; } function geometric(p = 0.5) { if (p <= 0 || p > 1) return void 0; return Math.floor(Math.log(Math.random()) / Math.log(1 - p)); } function cauchy() { let rr; let v1; let v2; do { v1 = 2 * Math.random() - 1; v2 = 2 * Math.random() - 1; rr = v1 * v1 + v2 * v2; } while (rr >= 1); return v1 / v2; } function normalPDF(x, m = 1, v = 0) { return Math.exp(-((x - m) ** 2) / (2 * v)) / Math.sqrt(2 * Math.PI * v); } var G = 7; var P = [ 0.9999999999998099, 676.5203681218851, -1259.1392167224028, 771.3234287776531, -176.6150291621406, 12.507343278686905, -0.13857109526572012, 9984369578019572e-21, 15056327351493116e-23 ]; function gamma(z) { if (z < 0.5) return Math.PI / (Math.sin(Math.PI * z) * gamma(1 - z)); z -= 1; let x = P[0]; for (let i = 1; i < G + 2; i++) x += P[i] / (z + i); const t = z + G + 0.5; return Math.sqrt(2 * Math.PI) * Math.pow(t, z + 0.5) * Math.exp(-t) * x; } function integrate(fn, xMin, xMax, dx = 1) { let result = 0; for (let x = xMin; x < xMax; x += dx) { result += fn(x) * dx || 0; } return result; } function chiCDF(chi, deg) { const int = integrate((t) => Math.pow(t, (deg - 2) / 2) * Math.exp(-t / 2), 0, chi); return 1 - int / Math.pow(2, deg / 2) / gamma(deg / 2); } // src/regression.ts var regression_exports = {}; __export(regression_exports, { bestPolynomial: () => bestPolynomial, coefficient: () => coefficient, exponential: () => exponential2, linear: () => linear, logarithmic: () => logarithmic, polynomial: () => polynomial2, power: () => power }); var import_core4 = require("@mathigon/core"); function evaluatePolynomial(regression, x) { let xs = 1; let t = regression[0]; for (let i = 1; i < regression.length; ++i) { xs *= x; t += xs * regression[i]; } return t; } function linear(data, throughOrigin = false) { let sX = 0; let sY = 0; let sXX = 0; let sXY = 0; const len = data.length; for (let n = 0; n < len; n++) { sX += data[n][0]; sY += data[n][1]; sXX += data[n][0] * data[n][0]; sXY += data[n][0] * data[n][1]; } if (throughOrigin) { const gradient2 = sXY / sXX; return [0, gradient2]; } const gradient = (len * sXY - sX * sY) / (len * sXX - sX * sX); const intercept = sY / len - gradient * sX / len; return [intercept, gradient]; } function exponential2(data) { const sum2 = [0, 0, 0, 0, 0, 0]; for (const d of data) { sum2[0] += d[0]; sum2[1] += d[1]; sum2[2] += d[0] * d[0] * d[1]; sum2[3] += d[1] * Math.log(d[1]); sum2[4] += d[0] * d[1] * Math.log(d[1]); sum2[5] += d[0] * d[1]; } const denominator = sum2[1] * sum2[2] - sum2[5] * sum2[5]; const a = Math.exp((sum2[2] * sum2[3] - sum2[5] * sum2[4]) / denominator); const b = (sum2[1] * sum2[4] - sum2[5] * sum2[3]) / denominator; return [a, b]; } function logarithmic(data) { const sum2 = [0, 0, 0, 0]; const len = data.length; for (const d of data) { sum2[0] += Math.log(d[0]); sum2[1] += d[1] * Math.log(d[0]); sum2[2] += d[1]; sum2[3] += Math.pow(Math.log(d[0]), 2); } const b = (len * sum2[1] - sum2[2] * sum2[0]) / (len * sum2[3] - sum2[0] * sum2[0]); const a = (sum2[2] - b * sum2[0]) / len; return [a, b]; } function power(data) { const sum2 = [0, 0, 0, 0]; const len = data.length; for (const d of data) { sum2[0] += Math.log(d[0]); sum2[1] += Math.log(d[1]) * Math.log(d[0]); sum2[2] += Math.log(d[1]); sum2[3] += Math.pow(Math.log(d[0]), 2); } const b = (len * sum2[1] - sum2[2] * sum2[0]) / (len * sum2[3] - sum2[0] * sum2[0]); const a = Math.exp((sum2[2] - b * sum2[0]) / len); return [a, b]; } function polynomial2(data, order = 2) { const X = data.map((d) => (0, import_core4.list)(order + 1).map((p) => Math.pow(d[0], p))); const XT = transpose(X); const y = data.map((d) => [d[1]]); const XTX = product(XT, X); const inv = inverse(XTX); const r = product(inv, XT, y); return r.map((x) => x[0]); } function coefficient(data, fn) { const total4 = data.reduce((sum2, d) => sum2 + d[1], 0); const mean2 = total4 / data.length; const ssyy = data.reduce((sum2, d) => sum2 + (d[1] - mean2) ** 2, 0); const sse = data.reduce((sum2, d) => sum2 + (d[1] - fn(d[0])) ** 2, 0); return 1 - sse / ssyy; } function bestPolynomial(data, threshold = 0.85, maxOrder = 8) { if (data.length <= 1) return void 0; for (let i = 1; i < maxOrder; ++i) { const reg = polynomial2(data, i); const fn = (x) => evaluatePolynomial(reg, x); const coeff = coefficient(data, fn); if (coeff >= threshold) return { order: i, coefficients: reg, fn }; } return void 0; } // src/statistics.ts var import_core5 = require("@mathigon/core"); function mean(values) { return values.length ? (0, import_core5.total)(values) / values.length : 0; } function quantile(values, p, method = 1) { const n = values.length; if (!n) return 0; const sorted = values.slice(0).sort((a, b) => a - b); if (p === 0) return sorted[0]; if (p === 1) return sorted[n - 1]; if (![1, 2, 3].includes(method)) throw new RangeError("Invalid quantile method."); const index = method === 1 ? n * p - 0.5 : ( // Matlab, Mathematica method === 2 ? (n - 1) * p : ( // Excel, NumPy, Google Docs, R, Python (option) (n + 1) * p - 1 ) ); if (Number.isInteger(index)) return sorted[index]; const floor = Math.floor(index); return lerp(sorted[floor], sorted[floor + 1], index - floor); } function median(values, method = 1) { return quantile(values, 0.5, method); } function mode(values) { const counts = /* @__PURE__ */ new Map(); let maxCount = -1; let result = void 0; for (const v of values) { if (!counts.has(v)) counts.set(v, 0); const newCount = counts.get(v) + 1; counts.set(v, newCount); if (newCount === maxCount) { result = void 0; } else if (newCount > maxCount) { maxCount = newCount; result = v; } } return result; } function variance(values) { if (!values.length) return void 0; const m = mean(values); const sum2 = values.reduce((a, v) => a + (v - m) ** 2, 0); return sum2 / (values.length - 1); } function stdDev(values) { const v = variance(values); return v ? Math.sqrt(v) : 0; } function covariance(aX, aY) { if (aX.length !== aY.length) throw new Error("Array length mismatch."); const sum2 = aX.reduce((a, v, i) => a + v * aY[i], 0); return (sum2 - (0, import_core5.total)(aX) * (0, import_core5.total)(aY) / aX.length) / aX.length; } function correlation(aX, aY) { if (aX.length !== aY.length) throw new Error("Array length mismatch."); const covarXY = covariance(aX, aY); const stdDevX = stdDev(aX); const stdDevY = stdDev(aY); return covarXY / (stdDevX * stdDevY); } // src/vector.ts var import_core6 = require("@mathigon/core"); var Vector = class _Vector extends Array { constructor(...args) { super(); for (const i of args) this.push(i); } /** Returns the magnitude of the Vector */ get magnitude() { let squares = 0; for (let i = 0; i < this.length; ++i) squares += this[i] ** 2; return Math.sqrt(squares); } /** Returns the unitVector of the Vector */ get unitVector() { return this.scale(1 / this.magnitude); } /** Scales this vector by a factor q. */ scale(q) { return this.map((x) => q * x); } // ------------------------------------------------------------------------- /** Calculates the sum of two vectors v1 and v2. */ static sum(v1, v2) { if (v1.length !== v2.length) throw new Error("Mismatched vector sizes."); return v1.map((v, i) => v + v2[i]); } /** Calculates the difference of two vectors v1 and v2. */ static difference(v1, v2) { if (v1.length !== v2.length) throw new Error("Mismatched vector sizes."); return v1.map((v, i) => v - v2[i]); } /** Calculates the element-wise product of two vectors v1 and v2. */ static product(v1, v2) { if (v1.length !== v2.length) throw new Error("Mismatched vector sizes."); return v1.map((v, i) => v * v2[i]); } /** Calculates the dot product of two vectors v1 and v2. */ static dot(v1, v2) { return (0, import_core6.total)(_Vector.product(v1, v2)); } /** Finds the cross product of two 3-dimensional vectors v1 and v2. */ static cross(v1, v2) { if (v1.length !== 3 || v2.length !== 3) { throw new Error("Cross product requires vectors of size 3."); } return new _Vector( v1[1] * v2[2] - v1[2] * v2[1], v1[2] * v2[0] - v1[0] * v2[2], v1[0] * v2[1] - v1[1] * v2[0] ); } /** Checks if two vectors are equal. */ static equals(v1, v2) { const n = v1.length; if (n !== v2.length) return false; for (let i = 0; i < n; ++i) if (!nearlyEquals(v1[i], v2[i])) return false; return true; } }; //# sourceMappingURL=index.cjs.js.map