use crate::algo_x_support::seed::cbrt_seed;
use crate::int::algos::support::limbs::{add_assign, bit_len, cmp};
use crate::int::algos::mul::mul_schoolbook::mul_schoolbook;
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(4);
pub(crate) fn icbrt_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, "icbrt scratch overflow");
let mut x = [0u64; SCRATCH_LIMBS];
cbrt_seed(n, bits, &mut x[..work]);
let three = [3u64];
let mut sq = [0u64; SCRATCH_LIMBS];
let mut q = [0u64; SCRATCH_LIMBS];
let mut r = [0u64; SCRATCH_LIMBS];
let mut y = [0u64; SCRATCH_LIMBS];
let mut rem3_buf = [0u64; SCRATCH_LIMBS];
loop {
let sq_work = (work * 2).min(SCRATCH_LIMBS);
for s in sq[..sq_work].iter_mut() {
*s = 0;
}
mul_schoolbook(&x[..work], &x[..work], &mut sq[..sq_work]);
div_rem_dispatch(n, &sq[..sq_work], &mut q[..work], &mut r[..sq_work]);
add_assign(&mut q[..work], &x[..work]);
add_assign(&mut q[..work], &x[..work]);
for v in y[..work].iter_mut() {
*v = 0;
}
rem3_buf[0] = 0;
div_rem_dispatch(&q[..work], &three, &mut y[..work], &mut rem3_buf[..1]);
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]);
}