use crate::algo_x_support::seed::sqrt_seed;
use crate::int::algos::support::limbs::{add_assign, bit_len, cmp, shr};
use crate::int::policy::div_rem::dispatch as div_rem_dispatch;
use crate::int::algos::support::limbs::max_n_limbs;
const SCRATCH_LIMBS: usize = max_n_limbs(2);
pub(crate) fn isqrt_newton(n: &[u64], out: &mut [u64]) {
for o in out.iter_mut() {
*o = 0;
}
let bits = bit_len(n);
if bits == 0 {
return;
}
if bits <= 1 {
out[0] = 1;
return;
}
let work = n.len() + 1;
debug_assert!(work <= SCRATCH_LIMBS, "isqrt scratch overflow");
let mut x = [0u64; SCRATCH_LIMBS];
sqrt_seed(n, bits, &mut x[..work]);
let mut q = [0u64; SCRATCH_LIMBS];
let mut r = [0u64; SCRATCH_LIMBS];
let mut y = [0u64; SCRATCH_LIMBS];
loop {
div_rem_dispatch(n, &x[..work], &mut q[..work], &mut r[..work]);
add_assign(&mut q[..work], &x[..work]);
shr(&q[..work], 1, &mut y[..work]);
if cmp(&y[..work], &x[..work]) >= 0 {
break;
}
x[..work].copy_from_slice(&y[..work]);
}
let copy_len = if out.len() < work { out.len() } else { work };
out[..copy_len].copy_from_slice(&x[..copy_len]);
}