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 #[inline]
61 fn div_rem_limb_with_reciprocal(&self, rhs: &Reciprocal) -> (Self, Limb) {
62 self.div_rem_with_reciprocal(rhs)
63 }
64}
65
66impl Div<Limb> for Limb {
67 type Output = Limb;
68
69 #[inline]
70 fn div(self, rhs: Limb) -> Self {
71 self.checked_div(rhs).expect("division by zero")
72 }
73}
74
75impl Div<&Limb> for Limb {
76 type Output = Limb;
77
78 #[inline]
79 fn div(self, rhs: &Limb) -> Self {
80 self / (*rhs)
81 }
82}
83
84impl Div<Limb> for &Limb {
85 type Output = Limb;
86
87 #[inline]
88 fn div(self, rhs: Limb) -> Limb {
89 (*self) / rhs
90 }
91}
92
93impl Div<&Limb> for &Limb {
94 type Output = Limb;
95
96 #[inline]
97 fn div(self, rhs: &Limb) -> Limb {
98 (*self) / (*rhs)
99 }
100}
101
102impl Div<NonZero<Limb>> for Limb {
103 type Output = Limb;
104
105 #[inline]
106 fn div(self, rhs: NonZero<Limb>) -> Self {
107 self.div_rem(rhs).0
108 }
109}
110
111impl Div<&NonZero<Limb>> for Limb {
112 type Output = Limb;
113
114 #[inline]
115 fn div(self, rhs: &NonZero<Limb>) -> Self {
116 self / (*rhs)
117 }
118}
119
120impl Div<NonZero<Limb>> for &Limb {
121 type Output = Limb;
122
123 #[inline]
124 fn div(self, rhs: NonZero<Limb>) -> Limb {
125 (*self) / rhs
126 }
127}
128
129impl Div<&NonZero<Limb>> for &Limb {
130 type Output = Limb;
131
132 #[inline]
133 fn div(self, rhs: &NonZero<Limb>) -> Limb {
134 (*self) / (*rhs)
135 }
136}
137
138impl RemLimb for Limb {
139 #[inline]
140 fn rem_limb(&self, rhs: NonZero<Limb>) -> Limb {
141 self.div_rem(rhs).1
142 }
143
144 fn rem_limb_with_reciprocal(&self, rhs: &Reciprocal) -> Limb {
145 self.div_rem_with_reciprocal(rhs).1
146 }
147}
148
149impl Rem<Limb> for Limb {
150 type Output = Limb;
151
152 #[inline]
153 fn rem(self, rhs: Limb) -> Self {
154 self.checked_rem(rhs).expect("division by zero")
155 }
156}
157
158impl Rem<&Limb> for Limb {
159 type Output = Limb;
160
161 #[inline]
162 fn rem(self, rhs: &Limb) -> Self {
163 self % (*rhs)
164 }
165}
166
167impl Rem<Limb> for &Limb {
168 type Output = Limb;
169
170 #[inline]
171 fn rem(self, rhs: Limb) -> Limb {
172 (*self) % rhs
173 }
174}
175
176impl Rem<&Limb> for &Limb {
177 type Output = Limb;
178
179 #[inline]
180 fn rem(self, rhs: &Limb) -> Limb {
181 (*self) % (*rhs)
182 }
183}
184
185impl Rem<NonZero<Limb>> for Limb {
186 type Output = Limb;
187
188 #[inline]
189 fn rem(self, rhs: NonZero<Limb>) -> Self {
190 self.div_rem(rhs).1
191 }
192}
193
194impl Rem<&NonZero<Limb>> for Limb {
195 type Output = Limb;
196
197 #[inline]
198 fn rem(self, rhs: &NonZero<Limb>) -> Self {
199 self % (*rhs)
200 }
201}
202
203impl Rem<NonZero<Limb>> for &Limb {
204 type Output = Limb;
205
206 #[inline]
207 fn rem(self, rhs: NonZero<Limb>) -> Limb {
208 (*self) % rhs
209 }
210}
211
212impl Rem<&NonZero<Limb>> for &Limb {
213 type Output = Limb;
214
215 #[inline]
216 fn rem(self, rhs: &NonZero<Limb>) -> Limb {
217 (*self) % (*rhs)
218 }
219}
220
221impl DivAssign<Limb> for Limb {
222 #[inline]
223 fn div_assign(&mut self, rhs: Limb) {
224 *self = (*self) / rhs;
225 }
226}
227
228impl DivAssign<&Limb> for Limb {
229 #[inline]
230 fn div_assign(&mut self, rhs: &Limb) {
231 *self = (*self) / (*rhs);
232 }
233}
234
235impl DivAssign<NonZero<Limb>> for Limb {
236 #[inline]
237 fn div_assign(&mut self, rhs: NonZero<Limb>) {
238 *self = (*self) / rhs;
239 }
240}
241
242impl DivAssign<&NonZero<Limb>> for Limb {
243 #[inline]
244 fn div_assign(&mut self, rhs: &NonZero<Limb>) {
245 *self = (*self) / (*rhs);
246 }
247}
248
249impl RemAssign<Limb> for Limb {
250 #[inline]
251 fn rem_assign(&mut self, rhs: Limb) {
252 *self = (*self) % rhs;
253 }
254}
255
256impl RemAssign<&Limb> for Limb {
257 #[inline]
258 fn rem_assign(&mut self, rhs: &Limb) {
259 *self = (*self) % (*rhs);
260 }
261}
262
263impl RemAssign<NonZero<Limb>> for Limb {
264 #[inline]
265 fn rem_assign(&mut self, rhs: NonZero<Limb>) {
266 *self = (*self) % rhs;
267 }
268}
269
270impl RemAssign<&NonZero<Limb>> for Limb {
271 #[inline]
272 fn rem_assign(&mut self, rhs: &NonZero<Limb>) {
273 *self = (*self) % (*rhs);
274 }
275}
276
277#[cfg(test)]
278#[allow(clippy::op_ref)]
279mod tests {
280 use super::{CheckedDiv, Limb};
281 use crate::NonZero;
282
283 #[test]
284 fn div_rem_ok() {
285 let n = Limb::from_u32(0xffff_ffff);
286 let d = NonZero::new(Limb::from_u32(0xfffe)).expect("ensured non-zero");
287 assert_eq!(n.div_rem(d), (Limb::from_u32(0x10002), Limb::from_u32(0x3)));
288 }
289
290 #[test]
291 fn checked_div() {
292 assert_eq!(
293 CheckedDiv::checked_div(&Limb::ONE, &Limb::ONE).into_option(),
294 Some(Limb::ONE)
295 );
296 assert_eq!(
297 CheckedDiv::checked_div(&Limb::MAX, &Limb::ZERO).into_option(),
298 None
299 );
300 }
301
302 #[test]
303 fn checked_rem() {
304 assert_eq!(
305 Limb::ONE.checked_rem(Limb::ONE).into_option(),
306 Some(Limb::ZERO)
307 );
308 assert_eq!(Limb::MAX.checked_rem(Limb::ZERO).into_option(), None);
309 }
310
311 #[test]
312 fn div_trait() {
313 let a = Limb::from(10u64);
314 let b = NonZero::new(Limb::from(2u64)).unwrap();
315 let c = Limb::from(5u64);
316
317 assert_eq!(a / b, c);
318 assert_eq!(a / &b, c);
319 assert_eq!(&a / b, c);
320 assert_eq!(&a / &b, c);
321 assert_eq!(a / &b.0, c);
322 assert_eq!(&a / b.0, c);
323 }
324
325 #[test]
326 fn div_assign_trait() {
327 let a = Limb::from(10u64);
328 let b = NonZero::new(Limb::from(2u64)).unwrap();
329 let c = Limb::from(5u64);
330
331 let mut res = a;
332 res /= b;
333 assert_eq!(res, c);
334 let mut res = a;
335 res /= &b;
336 assert_eq!(res, c);
337 let mut res = a;
338 res /= b.0;
339 assert_eq!(res, c);
340 let mut res = a;
341 res /= &b.0;
342 assert_eq!(res, c);
343 }
344
345 #[should_panic]
346 #[test]
347 fn div_zero() {
348 let _ = Limb::ONE / Limb::ZERO;
349 }
350
351 #[should_panic]
352 #[test]
353 fn div_ref_zero() {
354 let _ = &Limb::ONE / Limb::ZERO;
355 }
356
357 #[test]
358 fn rem_trait() {
359 let a = Limb::from(10u64);
360 let b = NonZero::new(Limb::from(3u64)).unwrap();
361 let c = Limb::from(1u64);
362
363 assert_eq!(a % b, c);
364 assert_eq!(a % &b, c);
365 assert_eq!(&a % b, c);
366 assert_eq!(&a % &b, c);
367 assert_eq!(a % &b.0, c);
368 assert_eq!(&a % b.0, c);
369 }
370
371 #[test]
372 fn rem_assign_trait() {
373 let a = Limb::from(10u64);
374 let b = NonZero::new(Limb::from(3u64)).unwrap();
375 let c = Limb::from(1u64);
376
377 let mut res = a;
378 res %= b;
379 assert_eq!(res, c);
380 let mut res = a;
381 res %= &b;
382 assert_eq!(res, c);
383 let mut res = a;
384 res %= b.0;
385 assert_eq!(res, c);
386 let mut res = a;
387 res %= &b.0;
388 assert_eq!(res, c);
389 }
390
391 #[should_panic]
392 #[test]
393 fn rem_zero() {
394 let _ = Limb::ONE % Limb::ZERO;
395 }
396
397 #[should_panic]
398 #[test]
399 fn rem_ref_zero() {
400 let _ = &Limb::ONE % Limb::ZERO;
401 }
402}