UNPKG

@astermind/astermind-pro

Version:

Astermind Pro - Premium ML Toolkit with Advanced RAG, Reranking, Summarization, and Information Flow Analysis

263 lines 7.88 kB
// src/math/index.ts — production-grade numerics for Ω // Backward compatible with previous exports; adds robust, stable helpers. // ---------- Constants export const EPS = 1e-12; // general epsilon for divides/sqrt export const DISK_EPS = 0.95; // strict radius for Poincaré-like ops export const MAX_EXP = 709; // ~ ln(Number.MAX_VALUE) export const MIN_EXP = -745; // ~ ln(Number.MIN_VALUE) // ---------- Constructors / guards export function zeros(n) { return new Float64Array(n); } export function isFiniteVec(a) { const n = a.length; for (let i = 0; i < n; i++) if (!Number.isFinite(a[i])) return false; return true; } export function asVec(a) { // Copy into Float64Array for consistent math perf return a instanceof Float64Array ? a : new Float64Array(Array.from(a)); } // ---------- Basic algebra (pure, allocation) export function dot(a, b) { const n = Math.min(a.length, b.length); let s = 0; for (let i = 0; i < n; i++) s += a[i] * b[i]; return s; } export function add(a, b) { const n = Math.min(a.length, b.length); const o = new Float64Array(n); for (let i = 0; i < n; i++) o[i] = a[i] + b[i]; return o; } export function scal(a, k) { const n = a.length; const o = new Float64Array(n); for (let i = 0; i < n; i++) o[i] = a[i] * k; return o; } export function hadamard(a, b) { const n = Math.min(a.length, b.length); const o = new Float64Array(n); for (let i = 0; i < n; i++) o[i] = a[i] * b[i]; return o; } export function tanhVec(a) { const n = a.length; const o = new Float64Array(n); for (let i = 0; i < n; i++) o[i] = Math.tanh(a[i]); return o; } // ---------- In-place variants (underscore suffix) to reduce GC export function add_(out, a, b) { const n = Math.min(out.length, a.length, b.length); for (let i = 0; i < n; i++) out[i] = a[i] + b[i]; return out; } export function scal_(out, a, k) { const n = Math.min(out.length, a.length); for (let i = 0; i < n; i++) out[i] = a[i] * k; return out; } export function hadamard_(out, a, b) { const n = Math.min(out.length, a.length, b.length); for (let i = 0; i < n; i++) out[i] = a[i] * b[i]; return out; } export function tanhVec_(out, a) { const n = Math.min(out.length, a.length); for (let i = 0; i < n; i++) out[i] = Math.tanh(a[i]); return out; } // ---------- Norms / normalization export function l2(a) { // robust L2 (avoids NaN on weird input) let s = 0; for (let i = 0; i < a.length; i++) s += a[i] * a[i]; return Math.sqrt(Math.max(0, s)); } export function normalizeL2(a, eps = EPS) { const nrm = l2(a); if (!(nrm > eps) || !Number.isFinite(nrm)) return new Float64Array(a.length); // zero vec const o = new Float64Array(a.length); const inv = 1 / nrm; for (let i = 0; i < a.length; i++) o[i] = a[i] * inv; return o; } export function clampVec(a, lo = -Infinity, hi = Infinity) { const n = a.length, o = new Float64Array(n); for (let i = 0; i < n; i++) o[i] = Math.min(hi, Math.max(lo, a[i])); return o; } // ---------- Stats export function mean(a) { if (a.length === 0) return 0; let s = 0; for (let i = 0; i < a.length; i++) s += a[i]; return s / a.length; } export function variance(a, mu = mean(a)) { if (a.length === 0) return 0; let s = 0; for (let i = 0; i < a.length; i++) { const d = a[i] - mu; s += d * d; } return s / a.length; } export function standardize(a) { const mu = mean(a); const v = variance(a, mu); const sd = Math.sqrt(Math.max(v, 0)); if (!(sd > EPS)) { // zero-variance edge: return zeros to avoid blowing up downstream return new Float64Array(a.length); } const o = new Float64Array(a.length); const inv = 1 / sd; for (let i = 0; i < a.length; i++) o[i] = (a[i] - mu) * inv; return o; } // ---------- Cosine (robust) export function cosine(a, b) { const n = Math.min(a.length, b.length); if (n === 0) return 0; let dotv = 0, na = 0, nb = 0; for (let i = 0; i < n; i++) { const ai = (a[i] ?? 0), bi = (b[i] ?? 0); dotv += ai * bi; na += ai * ai; nb += bi * bi; } const denom = Math.sqrt(Math.max(na * nb, EPS)); const v = dotv / denom; return Number.isFinite(v) ? v : 0; } // ---------- Stable softmax / log-sum-exp export function logSumExp(a) { let m = -Infinity; for (let i = 0; i < a.length; i++) if (a[i] > m) m = a[i]; if (!Number.isFinite(m)) m = 0; let s = 0; for (let i = 0; i < a.length; i++) s += Math.exp(Math.max(MIN_EXP, Math.min(MAX_EXP, a[i] - m))); return m + Math.log(Math.max(s, EPS)); } export function softmax(a) { const out = new Float64Array(a.length); const lse = logSumExp(a); for (let i = 0; i < a.length; i++) out[i] = Math.exp(Math.max(MIN_EXP, Math.min(MAX_EXP, a[i] - lse))); // tiny renorm to remove drift let s = 0; for (let i = 0; i < out.length; i++) s += out[i]; const inv = 1 / Math.max(s, EPS); for (let i = 0; i < out.length; i++) out[i] *= inv; return out; } // ---------- Argmax / Top-K export function argmax(a) { if (a.length === 0) return -1; let idx = 0; let m = (a[0] ?? -Infinity); for (let i = 1; i < a.length; i++) { const v = (a[i] ?? -Infinity); if (v > m) { m = v; idx = i; } } return idx; } export function topK(a, k) { const n = a.length; if (k <= 0 || n === 0) return []; const K = Math.min(k, n); // simple partial selection (O(nk)); fine for small k in UI const res = []; for (let i = 0; i < n; i++) { const v = (a[i] ?? -Infinity); if (res.length < K) { res.push({ index: i, value: v }); if (res.length === K) res.sort((x, y) => y.value - x.value); } else if (v > res[K - 1].value) { res[K - 1] = { index: i, value: v }; res.sort((x, y) => y.value - x.value); } } return res; } // ---------- Safe exp/log/sigmoid export function expSafe(x) { return Math.exp(Math.max(MIN_EXP, Math.min(MAX_EXP, x))); } export function log1pSafe(x) { // log(1+x) with guard (x>-1) const y = Math.max(x, -1 + EPS); return Math.log(1 + y); } export function sigmoid(x) { if (x >= 0) { const z = Math.exp(-Math.min(x, MAX_EXP)); return 1 / (1 + z); } else { const z = Math.exp(Math.max(x, MIN_EXP)); return z / (1 + z); } } // ---------- Hyperbolic (proxy) distance with strict disk clamp // Assumes inputs are already bounded; still clamps defensively. export function hDistProxy(a, b) { // clamp radii to avoid denom blow-ups let na = 0, nb = 0, sum = 0; for (let i = 0; i < a.length; i++) { const ai = Math.max(-DISK_EPS, Math.min(DISK_EPS, a[i])); const bi = Math.max(-DISK_EPS, Math.min(DISK_EPS, b[i])); na += ai * ai; nb += bi * bi; const d = ai - bi; sum += d * d; } const num = 2 * Math.sqrt(Math.max(0, sum)); const den = Math.max(EPS, (1 - na) * (1 - nb)); // smooth, monotone proxy; bounded growth; stable near boundary return Math.log1p(Math.min(2 * num / den, 1e12)); } // ---------- Small utilities for UI formatting export function fmtHead(a, n = 4, digits = 3) { return Array.from(a).slice(0, n).map(v => v.toFixed(digits)).join(", "); } // Re-export specialized math modules export * from './rff.js'; export * from './online-ridge.js'; export * from './krr.js'; //# sourceMappingURL=index.js.map