dashu_base/math/
root.rs

1use super::{CubicRoot, SquareRoot};
2use crate::{CubicRootRem, NormalizedRootRem, SquareRootRem};
3
4// TODO(next): forward sqrt to f32/f64 if std is enabled and the input is small enough.
5//             Implement after we have a benchmark. See https://github.com/Aatch/ramp/blob/master/src/int.rs#L579.
6
7impl SquareRoot for u8 {
8    type Output = u8;
9
10    #[inline]
11    fn sqrt(&self) -> Self::Output {
12        self.sqrt_rem().0
13    }
14}
15
16impl CubicRoot for u8 {
17    type Output = u8;
18
19    #[inline]
20    fn cbrt(&self) -> Self::Output {
21        self.cbrt_rem().0
22    }
23}
24
25macro_rules! impl_root_using_rootrem {
26    ($t:ty, $half:ty) => {
27        impl SquareRoot for $t {
28            type Output = $half;
29
30            #[inline]
31            fn sqrt(&self) -> $half {
32                if *self == 0 {
33                    return 0;
34                }
35
36                // normalize the input and call the normalized subroutine
37                let shift = self.leading_zeros() & !1; // make sure shift is divisible by 2
38                let (root, _) = (self << shift).normalized_sqrt_rem();
39                root >> (shift / 2)
40            }
41        }
42
43        impl CubicRoot for $t {
44            type Output = $half;
45
46            #[inline]
47            fn cbrt(&self) -> $half {
48                if *self == 0 {
49                    return 0;
50                }
51
52                // normalize the input and call the normalized subroutine
53                let mut shift = self.leading_zeros();
54                shift -= shift % 3; // make sure shift is divisible by 3
55                let (root, _) = (self << shift).normalized_cbrt_rem();
56                root >> (shift / 3)
57            }
58        }
59    };
60}
61
62impl_root_using_rootrem!(u16, u8);
63impl_root_using_rootrem!(u32, u16);
64impl_root_using_rootrem!(u64, u32);
65impl_root_using_rootrem!(u128, u64);