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.is_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.is_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 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 #[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 #[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 #[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; 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; 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}