quaeratin
Version:
An extended precision floating point library (as per Shewchuk) - precision only limited by overflow / underflow
170 lines • 5.56 kB
JavaScript
import { twoProduct } from '../basic/two-product.js';
import { twoSum } from '../basic/two-sum.js';
import { fastTwoSum } from '../basic/fast-two-sum.js';
import { eCompress } from './e-compress.js';
const f = 134217729; // 2**27 + 1;
// We *have* to do the below❗ The assignee is a getter❗ The assigned is a pure function❗
const tp = twoProduct;
const ts = twoSum;
const fts = fastTwoSum;
const compress = eCompress;
/**
* Returns the result of multiplying an expansion by a double.
*
* * see [Shewchuk](https://people.eecs.berkeley.edu/~jrs/papers/robustr.pdf)
*
* Theorem 19 (Shwechuk): Let e = sum_(i=1)^m(e_i) be a nonoverlapping expansion
* of m p-bit components, and const b be a p-bit value where p >= 4. Suppose that
* the components of e are sorted in order of increasing magnitude, except that
* any of the e_i may be zero. Then the following algorithm will produce a
* nonoverlapping expansion h such that h = sum_(i=1)^(2m)(h_i) = be, where the
* components of h are also in order of increasing magnitude, except that any of
* the h_i may be zero. Furthermore, if e is nonadjacent and round-to-even
* tiebreaking is used, then h is non-adjacent.
*
* @param e a double floating point expansion
* @param b a double
*/
function scaleExpansion(e, b) {
const m = e.length;
//const h: number[] = new Array(2*m);
let q_;
//[h[0], q] = tp(e[0], b);
// inlined (above line)
const a = e[0];
let q = a * b;
const c = f * a;
const ah = c - (c - a);
const al = a - ah;
const d = f * b;
const bh = d - (d - b);
const bl = b - bh;
const h = [];
//h[0] = (al*bl) - ((q - (ah*bh)) - (al*bh) - (ah*bl));
const hh = (al * bl) - ((q - (ah * bh)) - (al * bh) - (ah * bl));
if (hh !== 0) {
h.push(hh);
}
for (let i = 1; i < m; i++) {
//const [t, T] = tp(e[i], b);
// inlined (above line)
const a = e[i];
const T = a * b;
const c = f * a;
const ah = c - (c - a);
const al = a - ah;
const d = f * b;
const bh = d - (d - b);
const bl = b - bh;
const t = (al * bl) - ((T - (ah * bh)) - (al * bh) - (ah * bl));
//[h[2*i-1], q_] = ts(q, t);
// inlined (above line)
const x = q + t;
const bv = x - q;
//h[2*i-1] = (q - (x - bv)) + (t - bv);
//h.push((q - (x - bv)) + (t - bv));
const hh = (q - (x - bv)) + (t - bv);
if (hh !== 0) {
h.push(hh);
}
q_ = x;
//[h[2*i], q] = fts(T, q_);
// inlined (above line)
const xx = T + q_;
//h[2*i] = q_ - (xx - T);
//h.push(q_ - (xx - T));
const hhh = q_ - (xx - T);
if (hhh !== 0) {
h.push(hhh);
}
q = xx;
}
//h[2*m - 1] = q;
//h.push(q);
if (q !== 0 || h.length === 0) {
h.push(q);
}
//return eCompress(h);
return h;
}
/**
* Returns the result of multiplying an expansion by a double.
*
* * see [Shewchuk](https://people.eecs.berkeley.edu/~jrs/papers/robustr.pdf)
*
* Theorem 19 (Shwechuk): Let e = sum_(i=1)^m(e_i) be a nonoverlapping expansion
* of m p-bit components, and const b be a p-bit value where p >= 4. Suppose that
* the components of e are sorted in order of increasing magnitude, except that
* any of the e_i may be zero. Then the following algorithm will produce a
* nonoverlapping expansion h such that h = sum_(i=1)^(2m)(h_i) = be, where the
* components of h are also in order of increasing magnitude, except that any of
* the h_i may be zero. Furthermore, if e is nonadjacent and round-to-even
* tiebreaking is used, then h is non-adjacent.
*
* @param e a double floating point expansion
* @param b a double
*/
function scaleExpansion2(b, e) {
const m = e.length;
//const h: number[] = new Array(2*m);
let q_;
//[h[0], q] = tp(e[0], b);
// inlined (above line)
const a = e[0];
let q = a * b;
const c = f * a;
const ah = c - (c - a);
const al = a - ah;
const d = f * b;
const bh = d - (d - b);
const bl = b - bh;
const h = [];
//h[0] = (al*bl) - ((q - (ah*bh)) - (al*bh) - (ah*bl));
const hh = (al * bl) - ((q - (ah * bh)) - (al * bh) - (ah * bl));
if (hh !== 0) {
h.push(hh);
}
for (let i = 1; i < m; i++) {
//const [t, T] = tp(e[i], b);
// inlined (above line)
const a = e[i];
const T = a * b;
const c = f * a;
const ah = c - (c - a);
const al = a - ah;
const d = f * b;
const bh = d - (d - b);
const bl = b - bh;
const t = (al * bl) - ((T - (ah * bh)) - (al * bh) - (ah * bl));
//[h[2*i-1], q_] = ts(q, t);
// inlined (above line)
const x = q + t;
const bv = x - q;
//h[2*i-1] = (q - (x - bv)) + (t - bv);
//h.push((q - (x - bv)) + (t - bv));
const hh = (q - (x - bv)) + (t - bv);
if (hh !== 0) {
h.push(hh);
}
q_ = x;
//[h[2*i], q] = fts(T, q_);
// inlined (above line)
const xx = T + q_;
//h[2*i] = q_ - (xx - T);
//h.push(q_ - (xx - T));
const hhh = q_ - (xx - T);
if (hhh !== 0) {
h.push(hhh);
}
q = xx;
}
//h[2*m - 1] = q;
//h.push(q);
if (q !== 0 || h.length === 0) {
h.push(q);
}
//return eCompress(h);
return h;
}
export { scaleExpansion, scaleExpansion2 };
//# sourceMappingURL=scale-expansion.js.map