1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use super::{CubicRoot, SquareRoot};
use crate::{CubicRootRem, NormalizedRootRem, SquareRootRem};

// TODO(next): forward sqrt to f32/f64 if std is enabled and the input is small enough.
//             Implement after we have a benchmark. See https://github.com/Aatch/ramp/blob/master/src/int.rs#L579.

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
    }
}

macro_rules! impl_root_using_rootrem {
    ($t:ty, $half:ty) => {
        impl SquareRoot for $t {
            type Output = $half;

            #[inline]
            fn sqrt(&self) -> $half {
                if *self == 0 {
                    return 0;
                }

                // normalize the input and call the normalized subroutine
                let shift = self.leading_zeros() & !1; // make sure shift is divisible by 2
                let (root, _) = (self << shift).normalized_sqrt_rem();
                root >> (shift / 2)
            }
        }

        impl CubicRoot for $t {
            type Output = $half;

            #[inline]
            fn cbrt(&self) -> $half {
                if *self == 0 {
                    return 0;
                }

                // normalize the input and call the normalized subroutine
                let mut shift = self.leading_zeros();
                shift -= shift % 3; // make sure shift is divisible by 3
                let (root, _) = (self << shift).normalized_cbrt_rem();
                root >> (shift / 3)
            }
        }
    };
}

impl_root_using_rootrem!(u16, u8);
impl_root_using_rootrem!(u32, u16);
impl_root_using_rootrem!(u64, u32);
impl_root_using_rootrem!(u128, u64);