UNPKG

quaeratin

Version:

An extended precision floating point library (as per Shewchuk) - precision only limited by overflow / underflow

144 lines 3.71 kB
import { eCompress } from "./e-compress.js"; // We *have* to do the below❗ The assignee is a getter❗ The assigned is a pure function❗ const compress = eCompress; /** * Returns the result of adding two expansions. * * Theorem 13: Let e = sum_(i=1)^m(e_i) and f = sum_(i=1)^n(f_i) be strongly * nonoverlapping expansions of m and n p-bit components, respectively, where * p >= 4. Suppose that the components of both e and f are sorted in order of * increasing magnitude, except that any of the e_i or f_i may be zero. On a * machine whose arithmetic uses the round-to-even rule, the following algorithm * will produce a strongly nonoverlapping expansion h such that * sum_(i=1)^(m+n)(e_i + f_i) = e + f, where the components of h are also in * order of increasing magnitude, except that any of the h_i may be zero. * * See https://people.eecs.berkeley.edu/~jrs/papers/robustr.pdf */ function fastExpansionSum(e, f) { //const g = merge(e,f); // inlined (above line) const lenE = e.length; const lenF = f.length; let i = 0; let j = 0; const g = []; while (i < lenE && j < lenF) { if (e[i] === 0) { i++; continue; } if (f[j] === 0) { j++; continue; } if (Math.abs(e[i]) <= Math.abs(f[j])) { g.push(e[i]); i++; } else { g.push(f[j]); j++; } } while (i < lenE) { g.push(e[i]); i++; } while (j < lenF) { g.push(f[j]); j++; } if (g.length === 0) { return [0]; } // end inlined const len = g.length; if (len === 1) { return g; } //const h: number[] = new Array(len); const h = []; //const q: number; //[h[0], q] = fastTwoSum(g[1], g[0]); // inlined (above line) const a = g[1]; const b = g[0]; let q = a + b; //h[0] = b - (q - a); const hh = b - (q - a); if (hh !== 0) { h.push(hh); } //let j = 0; j = 0; for (let i = 2; i < len; i++) { //[h[i-1], q] = twoSum(q, g[i]); // inlined (above line) const b = g[i]; const R = q + b; const _ = R - q; //h[i-1] = (q - (R - _)) + (b - _); const hh = (q - (R - _)) + (b - _); if (hh !== 0) { h.push(hh); } q = R; } //h[len-1] = q; //h.push(q); if (q !== 0 || h.length === 0) { h.push(q); } //return compress(h); return h; } /** * Returns the result of merging an expansion e and f into a single expansion, * in order of nondecreasing magnitude (possibly with interspersed zeros). * (This function is zero-eliminating) * * * see [Shewchuk](https://people.eecs.berkeley.edu/~jrs/papers/robustr.pdf) * * @param e a floating point expansion * @param f another floating point expansion */ function merge(e, f) { const lenE = e.length; const lenF = f.length; let i = 0; let j = 0; const merged = []; while (i < lenE && j < lenF) { if (e[i] === 0) { i++; continue; } if (f[j] === 0) { j++; continue; } if (Math.abs(e[i]) <= Math.abs(f[j])) { merged.push(e[i]); i++; } else { merged.push(f[j]); j++; } } while (i < lenE) { merged.push(e[i]); i++; } while (j < lenF) { merged.push(f[j]); j++; } if (merged.length === 0) { return [0]; } return merged; } export { fastExpansionSum }; //# sourceMappingURL=fast-expansion-sum.js.map