Skip to content

Instantly share code, notes, and snippets.

@Yaffle
Created September 6, 2021 10:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Yaffle/678d64d40b38d363f0d233efadf73425 to your computer and use it in GitHub Desktop.
Save Yaffle/678d64d40b38d363f0d233efadf73425 to your computer and use it in GitHub Desktop.
continued fraction for sqrt(n)
function* continuedFractionForSqrt(n) {
// https://trizenx.blogspot.com/2018/10/continued-fraction-factorization-method.html
function floorDiv(a, b) {
return typeof a === "bigint" && typeof b === "bigint" ? a / b : Math.floor(a / b);
}
n = BigInt(n);
if (n < 0n) {
throw new RangeError();
}
const root = BigInt(sqrt(n));
const remainder = n - root * root;
const i = Number(root) * 2 <= Number.MAX_SAFE_INTEGER ? Number(root) : root;
yield i;
if (remainder !== 0n) {
// sqrt(n) = floor(sqrt(n)) + 1 / x
// expand continued fraction:
// x_k = floor(x_k) + 1 / x_(k+1)
// each x_k will have form x_k = (sqrt(n) + y_k) / z_k
const one = i / i;
let zprev = one;
let z = typeof i === "number" ? Number(remainder) : remainder;
let y = i;
do {
const q = floorDiv((i + y), z);
const ynew = q * z - y;
const znew = zprev + q * (y - ynew);
y = ynew;
zprev = z;
z = znew;
console.assert(one <= q && q <= i + i);
console.assert(one <= y && y <= i);
console.assert(one <= z && z <= i + i);
yield q;
} while (zprev !== one); //TODO: why is it cycling here - ?
console.assert(y === i && BigInt(z) === remainder && zprev === one);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment