frame.akima
Version:
A package for Akima interpolation
89 lines (88 loc) • 2.49 kB
JavaScript
/**
* Evaluates the polynomial of the segment corresponding to the specified x value.
* @param xVals
* @param segmentCoeffs
* @param x
* @returns
*/
export function evaluatePolySegment(xVals, segmentCoeffs, x) {
let i = binarySearch(xVals, x);
if (i < 0) {
i = -i - 2;
}
i = Math.max(0, Math.min(i, segmentCoeffs.length - 1));
return evaluatePoly(segmentCoeffs[i], x - xVals[i]);
}
/**
* Corresponds to java.util.Arrays.binarySearch().
* The insertion point is defined as the point at which the key would be inserted into the array: the index of the first element greater than
* the key, or a.length if all elements in the array are less than the specified key.
* @param a
* @param key
* @returns the index of the search key, if it is contained in the array. Otherwise it returns -(insertionPoint + 1)
*/
export function binarySearch(a, key) {
let low = 0;
let high = a.length - 1;
while (low <= high) {
const mid = (low + high) >>> 1; // tslint:disable-line:no-bitwise
const midVal = a[mid];
if (midVal < key) {
low = mid + 1;
}
else if (midVal > key) {
high = mid - 1;
}
else if (midVal === key) {
return mid;
}
else {
// values might be NaN
throw new Error('Invalid number encountered in binary search.');
}
}
return -(low + 1); // key not found
}
/**
* Evaluates the value of a polynomial.
* @param c contains the polynomial coefficients in ascending order.
* @param x
* @returns
*/
export function evaluatePoly(c, x) {
const n = c.length;
if (n === 0) {
return 0;
}
let v = c[n - 1];
for (let i = n - 2; i >= 0; i--) {
v = x * v + c[i];
}
return v;
}
/**
* Checks that a number sequence is strictly increasing and all values are finite.
* @param a
*/
export function checkStrictlyIncreasing(a) {
for (let i = 0; i < a.length; i++) {
if (!Number.isFinite(a[i])) {
throw new Error('Non-finite number detected.');
}
if (i > 0 && a[i] <= a[i - 1]) {
throw new Error('Number sequence is not strictly increasing.');
}
}
}
/**
* Trims top order polynomial coefficients which are zero.
* @param c
* @returns
*/
export function trimPoly(c) {
let n = c.length;
while (n > 1 && c[n - 1] === 0) {
n--;
}
return n === c.length ? c : c.subarray(0, n);
}