ruint/
div.rs

1use crate::{algorithms, Uint};
2use core::ops::{Div, DivAssign, Rem, RemAssign};
3
4impl<const BITS: usize, const LIMBS: usize> Uint<BITS, LIMBS> {
5    /// Computes `self / rhs`, returning [`None`] if `rhs == 0`.
6    #[inline]
7    #[must_use]
8    #[allow(clippy::missing_const_for_fn)] // False positive
9    pub fn checked_div(self, rhs: Self) -> Option<Self> {
10        if rhs.is_zero() {
11            return None;
12        }
13        Some(self.div(rhs))
14    }
15
16    /// Computes `self % rhs`, returning [`None`] if `rhs == 0`.
17    #[inline]
18    #[must_use]
19    #[allow(clippy::missing_const_for_fn)] // False positive
20    pub fn checked_rem(self, rhs: Self) -> Option<Self> {
21        if rhs.is_zero() {
22            return None;
23        }
24        Some(self.rem(rhs))
25    }
26
27    /// Computes `self / rhs` rounding up.
28    ///
29    /// # Panics
30    ///
31    /// Panics if `rhs == 0`.
32    #[inline]
33    #[must_use]
34    #[track_caller]
35    pub fn div_ceil(self, rhs: Self) -> Self {
36        let (q, r) = self.div_rem(rhs);
37        if r.is_zero() {
38            q
39        } else {
40            q + Self::from(1)
41        }
42    }
43
44    /// Computes `self / rhs` and `self % rhs`.
45    ///
46    /// # Panics
47    ///
48    /// Panics if `rhs == 0`.
49    #[inline]
50    #[must_use]
51    #[track_caller]
52    pub fn div_rem(mut self, mut rhs: Self) -> (Self, Self) {
53        algorithms::div(&mut self.limbs, &mut rhs.limbs);
54        (self, rhs)
55    }
56
57    /// Computes `self / rhs` rounding down.
58    ///
59    /// # Panics
60    ///
61    /// Panics if `rhs == 0`.
62    #[inline]
63    #[must_use]
64    #[track_caller]
65    pub fn wrapping_div(self, rhs: Self) -> Self {
66        self.div_rem(rhs).0
67    }
68
69    /// Computes `self % rhs`.
70    ///
71    /// # Panics
72    ///
73    /// Panics if `rhs == 0`.
74    #[inline]
75    #[must_use]
76    #[track_caller]
77    pub fn wrapping_rem(self, rhs: Self) -> Self {
78        self.div_rem(rhs).1
79    }
80}
81
82impl_bin_op!(Div, div, DivAssign, div_assign, wrapping_div);
83impl_bin_op!(Rem, rem, RemAssign, rem_assign, wrapping_rem);
84
85#[cfg(test)]
86mod tests {
87    use super::*;
88    use crate::{const_for, nlimbs};
89    use proptest::{prop_assume, proptest};
90
91    #[test]
92    fn test_div_ceil() {
93        const_for!(BITS in NON_ZERO {
94            const LIMBS: usize = nlimbs(BITS);
95            type U = Uint<BITS, LIMBS>;
96            proptest!(|(n: U, mut d: U)| {
97                d >>= BITS / 2; // make d small
98                prop_assume!(d != U::ZERO);
99                let qf = n / d;
100                let qc = n.div_ceil(d);
101                assert!(qf <= qc);
102                assert!(qf == qc || qf == qc - U::from(1));
103                if qf == qc {
104                    assert!(n % d == U::ZERO);
105                }
106            });
107        });
108    }
109
110    #[test]
111    fn test_divrem() {
112        const_for!(BITS in NON_ZERO {
113            const LIMBS: usize = nlimbs(BITS);
114            type U = Uint<BITS, LIMBS>;
115            proptest!(|(n: U, mut d: u64)| {
116                if BITS < 64 {
117                    d &= U::MASK;
118                }
119                if d == 0 {
120                    d = 1;
121                }
122                let d = U::from(d);
123                let (q, r) = n.div_rem(d);
124                assert!(r < d);
125                assert_eq!(q * d + r, n);
126            });
127            proptest!(|(n: U, mut d: U)| {
128                d >>= BITS / 2; // make d small
129                prop_assume!(d != U::ZERO);
130                let (q, r) = n.div_rem(d);
131                assert!(r < d);
132                assert_eq!(q * d + r, n);
133            });
134            proptest!(|(n: U, d: U)| {
135                prop_assume!(d != U::ZERO);
136                let (q, r) = n.div_rem(d);
137                assert!(r < d);
138                assert_eq!(q * d + r, n);
139            });
140        });
141    }
142}