crypto_bigint/limb/
div.rs1use core::slice;
4
5use crate::{
6 CheckedDiv, CtOption, Div, DivAssign, DivRemLimb, Limb, NonZero, Reciprocal, Rem, RemAssign,
7 RemLimb, UintRef,
8};
9
10impl Limb {
11 #[inline(always)]
13 #[must_use]
14 pub const fn div_rem(self, rhs: NonZero<Self>) -> (Limb, Limb) {
15 self.div_rem_with_reciprocal(&Reciprocal::new(rhs))
16 }
17
18 #[inline(always)]
21 #[must_use]
22 pub const fn div_rem_with_reciprocal(self, recip: &Reciprocal) -> (Limb, Limb) {
23 let mut quo = self;
24 let rem = UintRef::new_mut(slice::from_mut(&mut quo)).div_rem_limb_with_reciprocal(recip);
25 (quo, rem)
26 }
27
28 #[must_use]
31 pub const fn checked_div(self, rhs: Self) -> CtOption<Limb> {
32 let is_nz = rhs.is_nonzero();
33 let quo = self.div_rem(NonZero(Self::select(Limb::ONE, rhs, is_nz))).0;
34 CtOption::new(quo, is_nz)
35 }
36
37 #[must_use]
40 pub const fn checked_rem(self, rhs: Self) -> CtOption<Limb> {
41 let is_nz = rhs.is_nonzero();
42 let rem = self.div_rem(NonZero(Self::select(Limb::ONE, rhs, is_nz))).1;
43 CtOption::new(rem, is_nz)
44 }
45}
46
47impl CheckedDiv for Limb {
48 #[inline]
49 fn checked_div(&self, rhs: &Self) -> CtOption<Self> {
50 (*self).checked_div(*rhs)
51 }
52}
53
54impl DivRemLimb for Limb {
55 #[inline]
56 fn div_rem_limb(&self, rhs: NonZero<Limb>) -> (Self, Limb) {
57 self.div_rem(rhs)
58 }
59
60 fn div_rem_limb_with_reciprocal(&self, rhs: &Reciprocal) -> (Self, Limb) {
61 self.div_rem_with_reciprocal(rhs)
62 }
63}
64
65impl Div<Limb> for Limb {
66 type Output = Limb;
67
68 #[inline]
69 fn div(self, rhs: Limb) -> Self {
70 self.checked_div(rhs).expect("division by zero")
71 }
72}
73
74impl Div<&Limb> for Limb {
75 type Output = Limb;
76
77 #[inline]
78 fn div(self, rhs: &Limb) -> Self {
79 self / (*rhs)
80 }
81}
82
83impl Div<Limb> for &Limb {
84 type Output = Limb;
85
86 #[inline]
87 fn div(self, rhs: Limb) -> Limb {
88 (*self) / rhs
89 }
90}
91
92impl Div<&Limb> for &Limb {
93 type Output = Limb;
94
95 #[inline]
96 fn div(self, rhs: &Limb) -> Limb {
97 (*self) / (*rhs)
98 }
99}
100
101impl Div<NonZero<Limb>> for Limb {
102 type Output = Limb;
103
104 #[inline]
105 fn div(self, rhs: NonZero<Limb>) -> Self {
106 self.div_rem(rhs).0
107 }
108}
109
110impl Div<&NonZero<Limb>> for Limb {
111 type Output = Limb;
112
113 #[inline]
114 fn div(self, rhs: &NonZero<Limb>) -> Self {
115 self / (*rhs)
116 }
117}
118
119impl Div<NonZero<Limb>> for &Limb {
120 type Output = Limb;
121
122 #[inline]
123 fn div(self, rhs: NonZero<Limb>) -> Limb {
124 (*self) / rhs
125 }
126}
127
128impl Div<&NonZero<Limb>> for &Limb {
129 type Output = Limb;
130
131 #[inline]
132 fn div(self, rhs: &NonZero<Limb>) -> Limb {
133 (*self) / (*rhs)
134 }
135}
136
137impl RemLimb for Limb {
138 #[inline]
139 fn rem_limb(&self, rhs: NonZero<Limb>) -> Limb {
140 self.div_rem(rhs).1
141 }
142
143 fn rem_limb_with_reciprocal(&self, rhs: &Reciprocal) -> Limb {
144 self.div_rem_with_reciprocal(rhs).1
145 }
146}
147
148impl Rem<Limb> for Limb {
149 type Output = Limb;
150
151 #[inline]
152 fn rem(self, rhs: Limb) -> Self {
153 self.checked_rem(rhs).expect("division by zero")
154 }
155}
156
157impl Rem<&Limb> for Limb {
158 type Output = Limb;
159
160 #[inline]
161 fn rem(self, rhs: &Limb) -> Self {
162 self % (*rhs)
163 }
164}
165
166impl Rem<Limb> for &Limb {
167 type Output = Limb;
168
169 #[inline]
170 fn rem(self, rhs: Limb) -> Limb {
171 (*self) % rhs
172 }
173}
174
175impl Rem<&Limb> for &Limb {
176 type Output = Limb;
177
178 #[inline]
179 fn rem(self, rhs: &Limb) -> Limb {
180 (*self) % (*rhs)
181 }
182}
183
184impl Rem<NonZero<Limb>> for Limb {
185 type Output = Limb;
186
187 #[inline]
188 fn rem(self, rhs: NonZero<Limb>) -> Self {
189 self.div_rem(rhs).1
190 }
191}
192
193impl Rem<&NonZero<Limb>> for Limb {
194 type Output = Limb;
195
196 #[inline]
197 fn rem(self, rhs: &NonZero<Limb>) -> Self {
198 self % (*rhs)
199 }
200}
201
202impl Rem<NonZero<Limb>> for &Limb {
203 type Output = Limb;
204
205 #[inline]
206 fn rem(self, rhs: NonZero<Limb>) -> Limb {
207 (*self) % rhs
208 }
209}
210
211impl Rem<&NonZero<Limb>> for &Limb {
212 type Output = Limb;
213
214 #[inline]
215 fn rem(self, rhs: &NonZero<Limb>) -> Limb {
216 (*self) % (*rhs)
217 }
218}
219
220impl DivAssign<Limb> for Limb {
221 #[inline]
222 fn div_assign(&mut self, rhs: Limb) {
223 *self = (*self) / rhs;
224 }
225}
226
227impl DivAssign<&Limb> for Limb {
228 #[inline]
229 fn div_assign(&mut self, rhs: &Limb) {
230 *self = (*self) / (*rhs);
231 }
232}
233
234impl DivAssign<NonZero<Limb>> for Limb {
235 #[inline]
236 fn div_assign(&mut self, rhs: NonZero<Limb>) {
237 *self = (*self) / rhs;
238 }
239}
240
241impl DivAssign<&NonZero<Limb>> for Limb {
242 #[inline]
243 fn div_assign(&mut self, rhs: &NonZero<Limb>) {
244 *self = (*self) / (*rhs);
245 }
246}
247
248impl RemAssign<Limb> for Limb {
249 #[inline]
250 fn rem_assign(&mut self, rhs: Limb) {
251 *self = (*self) % rhs;
252 }
253}
254
255impl RemAssign<&Limb> for Limb {
256 #[inline]
257 fn rem_assign(&mut self, rhs: &Limb) {
258 *self = (*self) % (*rhs);
259 }
260}
261
262impl RemAssign<NonZero<Limb>> for Limb {
263 #[inline]
264 fn rem_assign(&mut self, rhs: NonZero<Limb>) {
265 *self = (*self) % rhs;
266 }
267}
268
269impl RemAssign<&NonZero<Limb>> for Limb {
270 #[inline]
271 fn rem_assign(&mut self, rhs: &NonZero<Limb>) {
272 *self = (*self) % (*rhs);
273 }
274}
275
276#[cfg(test)]
277mod tests {
278 use super::{CheckedDiv, Limb};
279 use crate::NonZero;
280
281 #[test]
282 fn div_rem_ok() {
283 let n = Limb::from_u32(0xffff_ffff);
284 let d = NonZero::new(Limb::from_u32(0xfffe)).expect("ensured non-zero");
285 assert_eq!(n.div_rem(d), (Limb::from_u32(0x10002), Limb::from_u32(0x3)));
286 }
287
288 #[test]
289 fn checked_div() {
290 assert_eq!(
291 CheckedDiv::checked_div(&Limb::ONE, &Limb::ONE).into_option(),
292 Some(Limb::ONE)
293 );
294 assert_eq!(
295 CheckedDiv::checked_div(&Limb::MAX, &Limb::ZERO).into_option(),
296 None
297 );
298 }
299
300 #[test]
301 fn checked_rem() {
302 assert_eq!(
303 Limb::ONE.checked_rem(Limb::ONE).into_option(),
304 Some(Limb::ZERO)
305 );
306 assert_eq!(Limb::MAX.checked_rem(Limb::ZERO).into_option(), None);
307 }
308}