commons-math-interpolation
Version:
A partial port of the Apache Commons Math Interpolation package, including Akima cubic spline interpolation and LOESS/LOWESS local regression.
53 lines • 1.97 kB
JavaScript
import { checkStrictlyIncreasing, trimPoly, evaluatePolySegment } from "./Utils.js";
export function createCubicSplineInterpolator(xVals, yVals) {
const segmentCoeffs = computeCubicPolyCoefficients(xVals, yVals);
const xValsCopy = Float64Array.from(xVals);
return (x) => evaluatePolySegment(xValsCopy, segmentCoeffs, x);
}
export function computeCubicPolyCoefficients(xVals, yVals) {
if (xVals.length != yVals.length) {
throw new Error("Dimension mismatch.");
}
if (xVals.length < 3) {
throw new Error("Number of points is too small.");
}
checkStrictlyIncreasing(xVals);
const n = xVals.length - 1;
const h = new Float64Array(n);
for (let i = 0; i < n; i++) {
h[i] = xVals[i + 1] - xVals[i];
}
const mu = new Float64Array(n);
const z = new Float64Array(n + 1);
mu[0] = 0;
z[0] = 0;
for (let i = 1; i < n; i++) {
const g = 2 * (xVals[i + 1] - xVals[i - 1]) - h[i - 1] * mu[i - 1];
mu[i] = h[i] / g;
z[i] = (3 * (yVals[i + 1] * h[i - 1] - yVals[i] * (xVals[i + 1] - xVals[i - 1]) + yVals[i - 1] * h[i]) /
(h[i - 1] * h[i]) - h[i - 1] * z[i - 1]) / g;
}
const b = new Float64Array(n);
const c = new Float64Array(n + 1);
const d = new Float64Array(n);
z[n] = 0;
c[n] = 0;
for (let i = n - 1; i >= 0; i--) {
const dx = h[i];
const dy = yVals[i + 1] - yVals[i];
c[i] = z[i] - mu[i] * c[i + 1];
b[i] = dy / dx - dx * (c[i + 1] + 2 * c[i]) / 3;
d[i] = (c[i + 1] - c[i]) / (3 * dx);
}
const segmentCoeffs = new Array(n);
for (let i = 0; i < n; i++) {
const coeffs = new Float64Array(4);
coeffs[0] = yVals[i];
coeffs[1] = b[i];
coeffs[2] = c[i];
coeffs[3] = d[i];
segmentCoeffs[i] = trimPoly(coeffs);
}
return segmentCoeffs;
}
//# sourceMappingURL=Cubic.js.map