use alloy_primitives::U256;
pub fn sqrt(a: &U256) -> U256 {
if a <= &U256::ONE {
return *a;
}
let mut aa = *a;
let mut xn = U256::ONE;
let two_128 = U256::ONE << 128;
if aa >= two_128 {
aa >>= 128;
xn <<= 64;
}
let two_64 = U256::ONE << 64;
if aa >= two_64 {
aa >>= 64;
xn <<= 32;
}
let two_32 = U256::ONE << 32;
if aa >= two_32 {
aa >>= 32;
xn <<= 16;
}
let two_16 = U256::ONE << 16;
if aa >= two_16 {
aa >>= 16;
xn <<= 8;
}
let two_8 = U256::ONE << 8;
if aa >= two_8 {
aa >>= 8;
xn <<= 4;
}
let two_4 = U256::ONE << 4;
if aa >= two_4 {
aa >>= 4;
xn <<= 2;
}
let two_2 = U256::ONE << 2;
if aa >= two_2 {
xn <<= 1;
}
xn = (xn * U256::from(3)) >> 1;
xn = (xn + (a / xn)) >> 1;
xn = (xn + (a / xn)) >> 1;
xn = (xn + (a / xn)) >> 1;
xn = (xn + (a / xn)) >> 1;
xn = (xn + (a / xn)) >> 1;
if xn > (a / xn) {
xn - U256::ONE
} else {
xn
}
}