dashu_base/ring/
div_rem.rs

1use super::{DivEuclid, DivRem, DivRemAssign, DivRemEuclid, RemEuclid};
2
3macro_rules! impl_div_rem_ops_prim {
4    ($($T:ty)*) => {$(
5        impl DivRem for $T {
6            type OutputDiv = $T;
7            type OutputRem = $T;
8            #[inline]
9            fn div_rem(self, rhs: $T) -> ($T, $T) {
10                (self / rhs, self % rhs)
11            }
12        }
13        impl DivRemAssign for $T {
14            type OutputRem = $T;
15            #[inline]
16            fn div_rem_assign(&mut self, rhs: $T) -> $T {
17                let r = *self % rhs;
18                *self /= rhs;
19                r
20            }
21        }
22        impl DivEuclid for $T {
23            type Output = $T;
24            #[inline]
25            fn div_euclid(self, rhs: $T) -> $T {
26                <$T>::div_euclid(self, rhs)
27            }
28        }
29        impl RemEuclid for $T {
30            type Output = $T;
31            #[inline]
32            fn rem_euclid(self, rhs: $T) -> $T {
33                <$T>::rem_euclid(self, rhs)
34            }
35        }
36        impl DivRemEuclid for $T {
37            type OutputDiv = $T;
38            type OutputRem = $T;
39            #[inline]
40            fn div_rem_euclid(self, rhs: $T) -> ($T, $T) {
41                let (q, r) = (self / rhs, self % rhs);
42
43                // depending on compiler to simplify the case for unsinged integers
44                #[allow(unused_comparisons)]
45                if r >= 0 {
46                    (q, r)
47                } else if rhs >= 0{
48                    (q - 1, r + rhs)
49                } else {
50                    (q + 1, r - rhs)
51                }
52            }
53        }
54    )*}
55}
56impl_div_rem_ops_prim!(u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize);
57
58#[cfg(test)]
59mod tests {
60    use super::*;
61
62    #[test]
63    fn test_simple() {
64        assert_eq!(7u32.div_rem(4), (1, 3));
65        assert_eq!(7u32.div_rem_euclid(4), (1, 3));
66        assert_eq!(7i32.div_rem(-4), (-1, 3));
67        assert_eq!(7i32.div_rem_euclid(-4), (-1, 3));
68        assert_eq!((-7i32).div_rem(4), (-1, -3));
69        assert_eq!((-7i32).div_rem_euclid(4), (-2, 1));
70        assert_eq!((-7i32).div_rem(-4), (1, -3));
71        assert_eq!((-7i32).div_rem_euclid(-4), (2, 1));
72
73        let mut n = 7u32;
74        let r = n.div_rem_assign(4);
75        assert!(n == 1 && r == 3);
76    }
77}