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

Function fpsqrt

src/big-decimal/utils.ts:87–119  ·  view source on GitHub ↗
(a: bigint, bits: number)

Source from the content-addressed store, hash-verified

85 * Converge until |x_{n+1} - x_n| <= 1 (one ULP in the fixed-point grid).
86 */
87export function fpsqrt(a: bigint, bits: number): bigint {
88 if (a === 0n) return 0n;
89 if (a < 0n) throw new RangeError('fpsqrt: negative input');
90
91 // as = a * scale = a << bits; the result is isqrt(as).
92 const as = a << BigInt(bits);
93
94 // Seed the final refinement. At low/medium precision the float-seeded Heron
95 // converges in a few full-width divisions and wins outright; at high
96 // precision a recursive giant-steps isqrt (root the top half, then refine)
97 // does ~3× fewer full-width divisions. Dispatch on `bits` (a plain number
98 // compare, no bitLength) so the hot low-precision path is unchanged — fpsqrt
99 // callers pass a ≈ O(1)·2^bits, so as ≈ 2^(2·bits) and bits ≥ FP_SQRT_GIANT_BITS
100 // ⇒ as ≳ SQRT_GIANT_MIN_BITS (and isqrtGiant falls back to flat Heron if not).
101 let x: bigint;
102 if (bits < FP_SQRT_GIANT_BITS) {
103 x = bigSqrtSeed(as);
104 let prev: bigint;
105 do {
106 prev = x;
107 x = (x + as / x) / 2n;
108 } while (bigintAbs(x - prev) > 1n);
109 } else {
110 x = isqrtGiant(as, bitLength(as));
111 }
112
113 // One more iteration, then pick whichever of {x, next} has x²
114 // closest to `as` (the true floor-root or one above it).
115 const next = (x + as / x) / 2n;
116 const diffX = bigintAbs(x * x - as);
117 const diffNext = bigintAbs(next * next - as);
118 return diffNext < diffX ? next : x;
119}
120
121/**
122 * Seed for an integer square root of `n`: a value within a few bits of

Callers 3

utils.test.tsFile · 0.90
transcendentals.tsFile · 0.90
fpatanFunction · 0.85

Calls 4

bigSqrtSeedFunction · 0.85
bigintAbsFunction · 0.85
isqrtGiantFunction · 0.85
bitLengthFunction · 0.85

Tested by

no test coverage detected