UNPKG

@davepagurek/flo-mat

Version:

Medial / Scale Axis Transform (MAT/SAT) Library.

89 lines (73 loc) 3.14 kB
// TODO - import from `flo-poly` in the future import { ddMultDouble2 } from "double-double"; import { ddAddDd } from "double-double"; import { γγ } from '../error-analysis/gamma.js'; // We *have* to do the below❗ The assignee is a getter❗ The assigned is a pure function❗ Otherwise code is too slow❗ const qmd = ddMultDouble2; const qaq = ddAddDd; const { abs } = Math; const γγ3 = γγ(3); /** * Deflates the given polynomial *approximately* by removing a factor (x - t). * * @param p a polynomial with coefficients given densely as an array of * double-double precision floating point numbers from highest to lowest power, * e.g. `[[0,5],[0,-3],[0,0]]` represents the polynomial `5x^2 - 3x` * @param pE the coefficient-wise absolute error of the input polynomial that * still need to be multiplied by γγ3, i.e. it is `γγ3` times too big. * @param t an evaluation point of the polynomial. * * @example * ```typescript * // The polynomial x^3 - 5x^2 + 8x - 4 has a root at 1 and a double root at 2 * ddDeflate([[0,1], [0,-5], [0,8], [0,-4]], [0,2]); //=> [[0,1], [0,-3], [0,2]] * ddDeflate([[0,1], [0,-3], [0,2], [0,2]); //=> [[0,1], [0,-1]] * ddDeflate([[0,1], [0,-1]], [0,1]); //=> [[0,1]] * ``` * * @doc */ function ddDeflateWithRunningError( p: number[][], pE: number[], t: number): { coeffs: number[][]; errBound: number[]; } { //-------------------------------------------------------------------------- // `var` -> a variable // `$var` -> the double precision approximation to `var` // `_var` -> the absolute value of $var (a prefix underscore on a variable means absolute value) // `var_` -> the error in var (a postfix underscore means error bound but should still be multiplied by 3*γ²) // `_var_` -> means both absolute value and absolute error bound // recall: `a*b`, where both `a` and `b` have errors |a| and |b| we get for the // * error bound of (a*b) === a_|b| + |a|b_ + |a*b| (when either of a and b is double) // * error bound of (a*b) === a_|b| + |a|b_ + 2|a*b| (when both a and b is double-double) // * error bound of (a+b) === a_ + b_ + |a+b| (when a and/or b is double or double-double) // * the returned errors need to be multiplied by 3γ² to get the true error // * can use either `$var` or `var[var.length-1]` (the approx value) in error calculations // due to multiplication by 3*γ² and not 3*u² //-------------------------------------------------------------------------- const d = p.length - 1; const bs = [p[0]]; // coefficients let b_ = pE[0]; // running error const bEs = [b_]; // coefficient-wise error bound for (let i=1; i<d; i++) { // p[i] + t*bs[i-1]; const a = bs[i-1]; const $m = t*a[1]; const _t = abs(t); const m_ = _t*b_ + abs($m); const pi = p[i]; const p_ = pE[i]; b_ = p_ + m_ + abs(pi[1] + $m); const b = qaq(pi,qmd(t,a)); bs.push(b); bEs.push(b_); } return { coeffs: bs, errBound: bEs.map(e => γγ3*e) }; } export { ddDeflateWithRunningError }