use super::{CubicRoot, SquareRoot};
use crate::{CubicRootRem, NormalizedRootRem, SquareRootRem};
impl SquareRoot for u8 {
type Output = u8;
#[inline]
fn sqrt(&self) -> Self::Output {
self.sqrt_rem().0
}
}
impl CubicRoot for u8 {
type Output = u8;
#[inline]
fn cbrt(&self) -> Self::Output {
self.cbrt_rem().0
}
}
#[cfg(feature = "std")]
const F64_SQRT_THRESHOLD: u128 = 4503599761588224;
#[cfg(feature = "std")]
impl SquareRoot for u16 {
type Output = u8;
#[inline]
fn sqrt(&self) -> u8 {
if *self == 0 {
return 0;
}
(*self as f32).sqrt().floor() as u8
}
}
#[cfg(feature = "std")]
impl SquareRoot for u32 {
type Output = u16;
#[inline]
fn sqrt(&self) -> u16 {
if *self == 0 {
return 0;
}
(*self as f64).sqrt().floor() as u16
}
}
#[cfg(feature = "std")]
impl SquareRoot for u64 {
type Output = u32;
#[inline]
fn sqrt(&self) -> u32 {
if *self == 0 {
return 0;
}
if (*self as u128) < F64_SQRT_THRESHOLD {
return (*self as f64).sqrt().floor() as u32;
}
let shift = self.leading_zeros() & !1; let (root, _) = (self << shift).normalized_sqrt_rem();
root >> (shift / 2)
}
}
#[cfg(feature = "std")]
impl SquareRoot for u128 {
type Output = u64;
#[inline]
fn sqrt(&self) -> u64 {
if *self == 0 {
return 0;
}
if *self < F64_SQRT_THRESHOLD {
return (*self as f64).sqrt().floor() as u64;
}
let shift = self.leading_zeros() & !1; let (root, _) = (self << shift).normalized_sqrt_rem();
root >> (shift / 2)
}
}
#[cfg(not(feature = "std"))]
macro_rules! impl_sqrt_using_rootrem {
($t:ty, $half:ty) => {
impl SquareRoot for $t {
type Output = $half;
#[inline]
fn sqrt(&self) -> $half {
if *self == 0 {
return 0;
}
let shift = self.leading_zeros() & !1; let (root, _) = (self << shift).normalized_sqrt_rem();
root >> (shift / 2)
}
}
};
}
#[cfg(not(feature = "std"))]
impl_sqrt_using_rootrem!(u16, u8);
#[cfg(not(feature = "std"))]
impl_sqrt_using_rootrem!(u32, u16);
#[cfg(not(feature = "std"))]
impl_sqrt_using_rootrem!(u64, u32);
#[cfg(not(feature = "std"))]
impl_sqrt_using_rootrem!(u128, u64);
macro_rules! impl_cbrt_using_cbrtrem {
($t:ty, $half:ty) => {
impl CubicRoot for $t {
type Output = $half;
#[inline]
fn cbrt(&self) -> $half {
if *self == 0 {
return 0;
}
let mut shift = self.leading_zeros();
shift -= shift % 3; let (root, _) = (self << shift).normalized_cbrt_rem();
root >> (shift / 3)
}
}
};
}
impl_cbrt_using_cbrtrem!(u16, u8);
impl_cbrt_using_cbrtrem!(u32, u16);
impl_cbrt_using_cbrtrem!(u64, u32);
impl_cbrt_using_cbrtrem!(u128, u64);