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