use fixed::traits::{FixedSigned, FixedUnsigned};
use crate::util::*;
#[inline]
pub fn sqrt_u<Val>(num: Val) -> Val
where
Val: FixedUnsigned,
{
debug_assert!(
Val::ZERO <= num,
"can not take square root of negative number!"
);
debug_assert!(0 != Val::INT_NBITS, "use `sqrt_u0` instead!");
debug_assert!(
0 < Val::INT_NBITS,
"cannot take square root of numbers without integer bits!"
);
debug_assert!(1 < Val::INT_NBITS, "use `sqrt_u1` instead!");
if num == Val::ZERO || num == fixed_one::<Val>() {
return num;
}
let mut pow: Val;
let mut res: Val;
if num < fixed_one::<Val>() {
pow = fixed_one::<Val>() >> 1u32;
while num <= pow.unwrapped_mul(pow) {
pow >>= 1u32;
}
res = pow;
} else {
pow = fixed_one::<Val>() << 1u32; while if let Some(p) = pow.checked_mul(pow) {
p <= num
} else {
false
} {
pow <<= 1u32;
}
res = pow >> 1u32;
}
for _ in 0..fixed_bits::<Val>() {
pow >>= 1u32;
let next_res = res + pow;
if if let Some(nr_sq) = next_res.checked_mul(next_res) {
nr_sq <= num
} else {
false
} {
res = next_res;
}
}
res
}
#[inline]
pub fn sqrt_u1<Val>(num: Val) -> Val
where
Val: FixedUnsigned,
{
debug_assert!(
Val::ZERO <= num,
"cannot take square root of negative number!"
);
debug_assert!(0 != Val::INT_NBITS, "use `sqrt_u0` instead!");
debug_assert!(
1 == Val::INT_NBITS,
"use `sqrt` for numbers with more integer bits!"
);
if num == Val::ZERO {
return num;
}
let mut pow: Val;
let mut res: Val;
pow = Val::DELTA << Val::FRAC_NBITS as u32; while num <= pow.unwrapped_mul(pow) {
pow >>= 1u32;
}
res = pow;
for _ in 0..fixed_bits::<Val>() {
pow >>= 1u32;
let next_res = res + pow;
if if let Some(nr_sq) = next_res.checked_mul(next_res) {
nr_sq <= num
} else {
false
} {
res = next_res;
}
}
res
}
#[inline]
pub fn sqrt_u0<Val>(num: Val) -> Val
where
Val: FixedUnsigned,
{
debug_assert!(
Val::ZERO <= num,
"can not take square root of negative number!"
);
debug_assert!(0 == Val::INT_NBITS, "use `sqrt_u` or `sqrt_u1` instead!");
if num == Val::ZERO {
return num;
}
let mut pow: Val;
let mut res: Val;
pow = Val::DELTA << (Val::FRAC_NBITS - 1) as u32; while num <= pow.unwrapped_mul(pow) {
pow >>= 1u32;
}
res = pow;
for _ in 0..fixed_bits::<Val>() {
pow >>= 1u32;
let next_res = res + pow;
if if let Some(nr_sq) = next_res.checked_mul(next_res) {
nr_sq <= num
} else {
false
} {
res = next_res;
}
}
res
}
#[inline]
pub fn sqrt_i<Val>(num: Val) -> Val
where
Val: FixedSigned,
{
debug_assert!(
Val::ZERO <= num,
"cannot take square root of negative number!"
);
debug_assert!(
0 < Val::INT_NBITS,
"cannot take square root of numbers without integer bits!"
);
debug_assert!(1 < Val::INT_NBITS, "use `sqrt_i1` instead!");
if num == Val::ZERO || num == fixed_one::<Val>() {
return num;
}
let mut pow: Val;
let mut res: Val;
if num < fixed_one::<Val>() {
pow = fixed_one::<Val>() >> 1u32;
while num <= pow.unwrapped_mul(pow) {
pow >>= 1u32;
}
res = pow;
} else {
let mut n: u32 = Val::INT_NBITS as u32 - 2;
pow = fixed_one::<Val>();
while if let Some(p) = pow.checked_mul(pow) {
p <= num && n != 0u32
} else {
false
} {
pow <<= 1u32;
n -= 1u32;
}
if n == 0 {
res = pow;
} else {
res = pow >> 1u32;
}
}
for _ in 0..fixed_bits::<Val>() {
pow >>= 1u32;
if pow == Val::ZERO {
break;
}
let next_res = res + pow;
if if let Some(nr_sq) = next_res.checked_mul(next_res) {
nr_sq <= num
} else {
false
} {
res = next_res;
}
}
res
}
#[inline]
pub fn sqrt_i1<Val>(num: Val) -> Val
where
Val: FixedSigned,
{
debug_assert!(
Val::ZERO <= num,
"cannot take square root of negative number!"
);
debug_assert!(
0 < Val::INT_NBITS,
"cannot take square root of numbers without integer bits!"
);
debug_assert!(
1 == Val::INT_NBITS,
"use `sqrt` for numbers with more integer bits!"
);
if num == Val::ZERO {
return num;
}
let mut pow: Val;
let mut res: Val;
pow = Val::DELTA << Val::FRAC_NBITS as u32 - 1; while num <= pow.unwrapped_mul(pow) {
pow >>= 1u32;
}
res = pow;
for _ in 0..fixed_bits::<Val>() {
pow >>= 1u32;
let next_res = res + pow;
if if let Some(nr_sq) = next_res.checked_mul(next_res) {
nr_sq <= num
} else {
false
} {
res = next_res;
}
}
res
}