locutus
Version:
Locutus other languages' standard libraries to JavaScript for fun and educational purposes
46 lines (45 loc) • 1.64 kB
JavaScript
const MAX_SAFE_ROOT = BigInt(Number.MAX_SAFE_INTEGER);
const FIRST_UNSAFE_ROOT_SQUARED = (MAX_SAFE_ROOT + 1n) * (MAX_SAFE_ROOT + 1n);
export function isqrt(n) {
// discuss at: https://locutus.io/python/isqrt/
// parity verified: Python 3.12
// original by: Kevin van Zonneveld (https://kvz.io)
// note 1: Returns the integer square root, rounding down to the nearest whole number.
// example 1: isqrt(15)
// returns 1: 3
// example 2: isqrt(16)
// returns 2: 4
// example 3: isqrt(0)
// returns 3: 0
if (typeof n === 'string' && /^[-+]?\d+$/.test(n.trim())) {
const parsed = BigInt(n);
if (parsed < 0n) {
throw new Error('isqrt() only accepts non-negative integers');
}
if (parsed >= FIRST_UNSAFE_ROOT_SQUARED) {
throw new RangeError('isqrt() only supports roots within JS safe integer precision');
}
const root = bigintSqrt(parsed);
if (root > MAX_SAFE_ROOT) {
throw new RangeError('isqrt() only supports roots within JS safe integer precision');
}
return Number(root);
}
const value = Number(n);
if (!Number.isFinite(value) || !Number.isSafeInteger(value) || value < 0) {
throw new Error('isqrt() only accepts non-negative integers');
}
return Math.floor(Math.sqrt(value));
}
function bigintSqrt(value) {
if (value < 2n) {
return value;
}
let x0 = value;
let x1 = (x0 + 1n) >> 1n;
while (x1 < x0) {
x0 = x1;
x1 = (x1 + value / x1) >> 1n;
}
return x0;
}