quaeratin
Version:
An extended precision floating point library (as per Shewchuk) - precision only limited by overflow / underflow
163 lines (137 loc) • 5.37 kB
text/typescript
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: number[], b: number): number[] {
const m = e.length;
//const h: number[] = new Array(2*m);
let q_: number;
//[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: number[] = [];
//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: number, e: number[]): number[] {
const m = e.length;
//const h: number[] = new Array(2*m);
let q_: number;
//[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: number[] = [];
//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 }