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