MCPcopy Create free account
hub / github.com/cortex-js/compute-engine / add

Function add

src/compute-engine/numerics/rationals.ts:74–115  ·  view source on GitHub ↗
(lhs: Rational, rhs: Rational)

Source from the content-addressed store, hash-verified

72 * magnitude is out of the double range.
73 */
74export function rationalAsFloat(x: Rational): number {
75 const n = Number(x[0]);
76 const d = Number(x[1]);
77 if (typeof x[0] === 'bigint' && (!Number.isFinite(n) || !Number.isFinite(d)))
78 return bigRatioToFloat(x[0], x[1] as bigint);
79 return n / d;
80}
81
82/**
83 * The double nearest `n/d` for bigints of any size (`d ≠ 0`), computed
84 * without converting `n` or `d` to a double first.
85 *
86 * The quotient is scaled by a power of two `2^-e` so that its integer part
87 * `q` has 64 or 65 bits, one more than a double can hold. The lowest bit of
88 * `q` is set when the division has a remainder, so the conversion
89 * `Number(q)`, which rounds to 53 bits, rounds a truncated value that is
90 * just above a halfway point in the correct direction. The scale `2^e` is
91 * then applied in two steps, so that `2^(e/2)` stays in the double range
92 * for every `|e|` up to about 2046; beyond that the product is `0` or
93 * `±Infinity`, which is the nearest double. Multiplying by a power of two
94 * is exact while the result is a normal double, so a normal result is
95 * rounded once, by `Number(q)`.
96 *
97 * A subnormal result (below `2^-1022`) has fewer than 53 significant bits,
98 * so the multiplication by `2^e` would round a second time, and two
99 * roundings can give the wrong double: `(2^54 + 1)/2^1129` is just above
100 * half of `2^-1074`, but `Number(q)` rounds it to exactly half, and the
101 * product then rounds the tie to `0`. So when the value can be below
102 * `2^-1022`, the quotient `a·2^1074/b` is rounded to an integer `k` with
103 * the remainder, half to even, and the result is `k·2^-1074`, which is
104 * exact. When `k` is `2^52` or more, the value is normal and takes the
105 * path above.
106 */
107function bigRatioToFloat(n: bigint, d: bigint): number {
108 if (d === 0n) return n === 0n ? NaN : n > 0n ? Infinity : -Infinity;
109 if (n === 0n) return 0;
110 const negative = n < 0n !== d < 0n;
111 const a = n < 0n ? -n : n;
112 const b = d < 0n ? -d : d;
113 const la = a.toString(2).length;
114 const lb = b.toString(2).length;
115 // `a/b < 2^(la - lb + 1)`, so the value can be subnormal only when
116 // `la - lb + 1 <= -1022`.
117 if (la - lb <= -1023) {
118 const num = a << 1074n;

Callers 7

invMethod · 0.90
addMethod · 0.90
sqrtMethod · 0.90
absMethod · 0.90
addToBucketsMethod · 0.90
sumMethod · 0.90
addComponentsFunction · 0.90

Calls 2

isBigRationalFunction · 0.85
isFiniteMethod · 0.45

Tested by

no test coverage detected