UNPKG

dsp-collection

Version:

A collection of JavaScript modules for digital signal processing (written in TypeScript)

117 lines 3.39 kB
export function fuzzyEquals(a, b, eps) { if (!isFinite(a) || !isFinite(b)) { return false; } if (a == b) { return true; } const diff = Math.abs(a - b); if (diff <= eps) { return true; } const mag = Math.max(Math.abs(a), Math.abs(b)); return diff <= mag * eps; } export function isFuzzyInteger(i, eps) { return Math.abs(i - Math.round(i)) <= eps; } export function isPowerOf2(i) { if (!Number.isSafeInteger(i) || i < 1 || i > 0x40000000) { return false; } return (i & (i - 1)) == 0; } export function getNextPowerOf2(x) { if (!isFinite(x)) { return NaN; } let n = 1; while (n <= x) { n *= 2; } return n; } export function floorLog2(x) { if (x > 0x7FFFFFFF || x < 1) { throw new Error("Argument is not a valid integer."); } return 31 - Math.clz32(x); } export function hyperbolicDecline(t, a, b) { switch (b) { case 1: { return 1 / (1 + a * t); } case 0: { return Math.exp(-a * t); } case -1: { return Math.max(0, 1 - a * t); } default: { return 1 / (1 + b * a * t) ** (1 / b); } } } export function simpleMovingAverage(a, windowWidth, shift = false) { if (windowWidth < 2 || !Number.isSafeInteger(windowWidth)) { throw new Error("Specified window width is not valid for SMA."); } const len = a.length; const a2 = new Float64Array(len); const halfWindowWidth = Math.floor(windowWidth / 2); const posShift = (shift && windowWidth % 2 == 0) ? 1 : 0; const extendedLen = len + halfWindowWidth; let movingSum = 0; let n = 0; for (let p = 0; p < extendedLen; p++) { if (p >= windowWidth) { movingSum -= a[p - windowWidth]; n--; } if (p < len) { movingSum += a[p]; n++; } const p2 = p - halfWindowWidth + posShift; if (p2 >= 0 && p2 < len) { a2[p2] = movingSum / n; } } return a2; } export function triangularMovingAverage(a, windowWidth) { if (windowWidth < 4 || !Number.isSafeInteger(windowWidth)) { throw new Error("Specified window width is not valid for TMA."); } const w1 = Math.floor(windowWidth / 2); const w2 = windowWidth - w1; const a1 = simpleMovingAverage(a, w1); const a2 = simpleMovingAverage(a1, w2, true); return a2; } export function triangularMovingAverageRef(a, windowWidth) { if (windowWidth < 4 || !Number.isSafeInteger(windowWidth)) { throw new Error("Specified window width is not valid for TMA."); } const len = a.length; const a2 = new Float64Array(len); for (let p = 0; p < len; p++) { a2[p] = computeTriangularAverageAt(a, p, windowWidth); } return a2; } function computeTriangularAverageAt(a, p, windowWidth) { const len = a.length; const p1 = Math.max(0, Math.ceil(p - windowWidth / 2 + 0.1)); const p2 = Math.min(len - 1, Math.floor(p + windowWidth / 2 - 0.1)); let sum = 0; let weightSum = 0; for (let i = p1; i <= p2; i++) { const weight = 1 - Math.abs(i - p) / (windowWidth / 2); sum += a[i] * weight; weightSum += weight; } return sum / weightSum; } //# sourceMappingURL=MathUtils.js.map