malachite_base/num/arithmetic/div_mod.rs
1// Copyright © 2026 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use crate::fail_on_untested_path;
10use crate::num::arithmetic::mod_mul::{limbs_invert_limb_u32, limbs_invert_limb_u64};
11use crate::num::arithmetic::traits::{
12 CeilingDivAssignMod, CeilingDivAssignNegMod, CeilingDivMod, CeilingDivNegMod, DivAssignMod,
13 DivAssignModPrecomputed, DivAssignRem, DivMod, DivModPrecomputed, DivRem, UnsignedAbs,
14};
15use crate::num::basic::integers::USIZE_IS_U32;
16use crate::num::basic::signeds::PrimitiveSigned;
17use crate::num::basic::unsigneds::PrimitiveUnsigned;
18use crate::num::conversion::traits::{ExactFrom, HasHalf, JoinHalves, SplitInHalf, WrappingFrom};
19use crate::num::logic::traits::LeadingZeros;
20
21fn div_mod_unsigned<T: PrimitiveUnsigned>(x: T, other: T) -> (T, T) {
22 let q = x / other;
23 (q, x - q * other)
24}
25
26fn div_assign_mod_unsigned<T: PrimitiveUnsigned>(x: &mut T, other: T) -> T {
27 let original = *x;
28 *x /= other;
29 original - *x * other
30}
31
32fn ceiling_div_neg_mod_unsigned<T: PrimitiveUnsigned>(x: T, other: T) -> (T, T) {
33 let (quotient, remainder) = x.div_mod(other);
34 if remainder == T::ZERO {
35 (quotient, T::ZERO)
36 } else {
37 // Here remainder != 0, so other > 1, so quotient < T::MAX.
38 (quotient + T::ONE, other - remainder)
39 }
40}
41
42fn ceiling_div_assign_neg_mod_unsigned<T: PrimitiveUnsigned>(x: &mut T, other: T) -> T {
43 let remainder = x.div_assign_mod(other);
44 if remainder == T::ZERO {
45 T::ZERO
46 } else {
47 // Here remainder != 0, so other > 1, so self < T::MAX.
48 *x += T::ONE;
49 other - remainder
50 }
51}
52
53macro_rules! impl_div_mod_unsigned {
54 ($t:ident) => {
55 impl DivMod<$t> for $t {
56 type DivOutput = $t;
57 type ModOutput = $t;
58
59 /// Divides a number by another number, returning the quotient and remainder. The
60 /// quotient is rounded towards negative infinity.
61 ///
62 /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$.
63 ///
64 /// $$
65 /// f(x, y) = \left ( \left \lfloor \frac{x}{y} \right \rfloor, \space
66 /// x - y\left \lfloor \frac{x}{y} \right \rfloor \right ).
67 /// $$
68 ///
69 /// # Worst-case complexity
70 /// Constant time and additional memory.
71 ///
72 /// # Panics
73 /// Panics if `other` is 0.
74 ///
75 /// # Examples
76 /// See [here](super::div_mod#div_mod).
77 #[inline]
78 fn div_mod(self, other: $t) -> ($t, $t) {
79 div_mod_unsigned(self, other)
80 }
81 }
82
83 impl DivAssignMod<$t> for $t {
84 type ModOutput = $t;
85
86 /// Divides a number by another number in place, returning the remainder. The quotient
87 /// is rounded towards negative infinity.
88 ///
89 /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$.
90 ///
91 /// $$
92 /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor,
93 /// $$
94 /// $$
95 /// x \gets \left \lfloor \frac{x}{y} \right \rfloor.
96 /// $$
97 ///
98 /// # Worst-case complexity
99 /// Constant time and additional memory.
100 ///
101 /// # Panics
102 /// Panics if `other` is 0.
103 ///
104 /// # Examples
105 /// See [here](super::div_mod#div_assign_mod).
106 #[inline]
107 fn div_assign_mod(&mut self, other: $t) -> $t {
108 div_assign_mod_unsigned(self, other)
109 }
110 }
111
112 impl DivRem<$t> for $t {
113 type DivOutput = $t;
114 type RemOutput = $t;
115
116 /// Divides a number by another number, returning the quotient and remainder. The
117 /// quotient is rounded towards zero.
118 ///
119 /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$.
120 ///
121 /// $$
122 /// f(x, y) = \left ( \left \lfloor \frac{x}{y} \right \rfloor, \space
123 /// x - y\left \lfloor \frac{x}{y} \right \rfloor \right ).
124 /// $$
125 ///
126 /// For unsigned integers, `div_rem` is equivalent to `div_mod`.
127 ///
128 /// # Worst-case complexity
129 /// Constant time and additional memory.
130 ///
131 /// # Panics
132 /// Panics if `other` is 0.
133 ///
134 /// # Examples
135 /// See [here](super::div_mod#div_rem).
136 #[inline]
137 fn div_rem(self, other: $t) -> ($t, $t) {
138 self.div_mod(other)
139 }
140 }
141
142 impl DivAssignRem<$t> for $t {
143 type RemOutput = $t;
144
145 /// Divides a number by another number in place, returning the remainder. The quotient
146 /// is rounded towards zero.
147 ///
148 /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$.
149 ///
150 /// $$
151 /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor,
152 /// $$
153 /// $$
154 /// x \gets \left \lfloor \frac{x}{y} \right \rfloor.
155 /// $$
156 ///
157 /// For unsigned integers, `div_assign_rem` is equivalent to `div_assign_mod`.
158 ///
159 /// # Worst-case complexity
160 /// Constant time and additional memory.
161 ///
162 /// # Panics
163 /// Panics if `other` is 0.
164 ///
165 /// # Examples
166 /// See [here](super::div_mod#div_assign_rem).
167 #[inline]
168 fn div_assign_rem(&mut self, other: $t) -> $t {
169 self.div_assign_mod(other)
170 }
171 }
172
173 impl CeilingDivNegMod<$t> for $t {
174 type DivOutput = $t;
175 type ModOutput = $t;
176
177 /// Divides a number by another number, returning the ceiling of the quotient and the
178 /// remainder of the negative of the first number divided by the second.
179 ///
180 /// The quotient and remainder satisfy $x = qy - r$ and $0 \leq r < y$.
181 ///
182 /// $$
183 /// f(x, y) = \left ( \left \lceil \frac{x}{y} \right \rceil, \space
184 /// y\left \lceil \frac{x}{y} \right \rceil - x \right ).
185 /// $$
186 ///
187 /// # Worst-case complexity
188 /// Constant time and additional memory.
189 ///
190 /// # Panics
191 /// Panics if `other` is 0.
192 ///
193 /// # Examples
194 /// See [here](super::div_mod#ceiling_div_neg_mod).
195 #[inline]
196 fn ceiling_div_neg_mod(self, other: $t) -> ($t, $t) {
197 ceiling_div_neg_mod_unsigned(self, other)
198 }
199 }
200
201 impl CeilingDivAssignNegMod<$t> for $t {
202 type ModOutput = $t;
203
204 /// Divides a number by another number in place, returning the remainder of the negative
205 /// of the first number divided by the second.
206 ///
207 /// The quotient and remainder satisfy $x = qy - r$ and $0 \leq r < y$.
208 ///
209 /// $$
210 /// f(x, y) = y\left \lceil \frac{x}{y} \right \rceil - x,
211 /// $$
212 /// $$
213 /// x \gets \left \lceil \frac{x}{y} \right \rceil.
214 /// $$
215 ///
216 /// # Worst-case complexity
217 /// Constant time and additional memory.
218 ///
219 /// # Panics
220 /// Panics if `other` is 0.
221 ///
222 /// # Examples
223 /// See [here](super::div_mod#ceiling_div_assign_neg_mod).
224 #[inline]
225 fn ceiling_div_assign_neg_mod(&mut self, other: $t) -> $t {
226 ceiling_div_assign_neg_mod_unsigned(self, other)
227 }
228 }
229 };
230}
231apply_to_unsigneds!(impl_div_mod_unsigned);
232
233fn div_mod_signed<
234 U: PrimitiveUnsigned,
235 S: PrimitiveSigned + ExactFrom<U> + UnsignedAbs<Output = U> + WrappingFrom<U>,
236>(
237 x: S,
238 other: S,
239) -> (S, S) {
240 let (quotient, remainder) = if (x >= S::ZERO) == (other >= S::ZERO) {
241 let (quotient, remainder) = x.unsigned_abs().div_mod(other.unsigned_abs());
242 (S::exact_from(quotient), remainder)
243 } else {
244 let (quotient, remainder) = x.unsigned_abs().ceiling_div_neg_mod(other.unsigned_abs());
245 (S::wrapping_from(quotient).wrapping_neg(), remainder)
246 };
247 (
248 quotient,
249 if other >= S::ZERO {
250 S::exact_from(remainder)
251 } else {
252 -S::exact_from(remainder)
253 },
254 )
255}
256
257fn div_rem_signed<T: PrimitiveSigned>(x: T, other: T) -> (T, T) {
258 let q = x.checked_div(other).unwrap();
259 (q, x - q * other)
260}
261
262fn div_assign_rem_signed<T: PrimitiveSigned>(x: &mut T, other: T) -> T {
263 let original = *x;
264 *x = x.checked_div(other).unwrap();
265 original - *x * other
266}
267
268fn ceiling_div_mod_signed<
269 U: PrimitiveUnsigned,
270 T: PrimitiveSigned + ExactFrom<U> + UnsignedAbs<Output = U> + WrappingFrom<U>,
271>(
272 x: T,
273 other: T,
274) -> (T, T) {
275 let (quotient, remainder) = if (x >= T::ZERO) == (other >= T::ZERO) {
276 let (quotient, remainder) = x.unsigned_abs().ceiling_div_neg_mod(other.unsigned_abs());
277 (T::exact_from(quotient), remainder)
278 } else {
279 let (quotient, remainder) = x.unsigned_abs().div_mod(other.unsigned_abs());
280 (T::wrapping_from(quotient).wrapping_neg(), remainder)
281 };
282 (
283 quotient,
284 if other >= T::ZERO {
285 -T::exact_from(remainder)
286 } else {
287 T::exact_from(remainder)
288 },
289 )
290}
291
292macro_rules! impl_div_mod_signed {
293 ($t:ident) => {
294 impl DivMod<$t> for $t {
295 type DivOutput = $t;
296 type ModOutput = $t;
297
298 /// Divides a number by another number, returning the quotient and remainder. The
299 /// quotient is rounded towards negative infinity, and the remainder has the same sign
300 /// as the second number.
301 ///
302 /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$.
303 ///
304 /// $$
305 /// f(x, y) = \left ( \left \lfloor \frac{x}{y} \right \rfloor, \space
306 /// x - y\left \lfloor \frac{x}{y} \right \rfloor \right ).
307 /// $$
308 ///
309 /// # Worst-case complexity
310 /// Constant time and additional memory.
311 ///
312 /// # Panics
313 /// Panics if `other` is 0, or if `self` is `$t::MIN` and `other` is -1.
314 ///
315 /// # Examples
316 /// See [here](super::div_mod#div_mod).
317 #[inline]
318 fn div_mod(self, other: $t) -> ($t, $t) {
319 div_mod_signed(self, other)
320 }
321 }
322
323 impl DivAssignMod<$t> for $t {
324 type ModOutput = $t;
325
326 /// Divides a number by another number in place, returning the remainder. The quotient
327 /// is rounded towards negative infinity, and the remainder has the same sign as the
328 /// second number.
329 ///
330 /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$.
331 ///
332 /// $$
333 /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor,
334 /// $$
335 /// $$
336 /// x \gets \left \lfloor \frac{x}{y} \right \rfloor.
337 /// $$
338 ///
339 /// # Worst-case complexity
340 /// Constant time and additional memory.
341 ///
342 /// # Panics
343 /// Panics if `other` is 0, or if `self` is `$t::MIN` and `other` is -1.
344 ///
345 /// # Examples
346 /// See [here](super::div_mod#div_assign_mod).
347 #[inline]
348 fn div_assign_mod(&mut self, other: $t) -> $t {
349 let (q, r) = self.div_mod(other);
350 *self = q;
351 r
352 }
353 }
354
355 impl DivRem<$t> for $t {
356 type DivOutput = $t;
357 type RemOutput = $t;
358
359 /// Divides a number by another number, returning the quotient and remainder. The
360 /// quotient is rounded towards zero and the remainder has the same sign as the
361 /// dividend.
362 ///
363 /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$.
364 ///
365 /// $$
366 /// f(x, y) = \left ( \operatorname{sgn}(xy) \left \lfloor \left | \frac{x}{y} \right |
367 /// \right \rfloor, \space
368 /// x - y \operatorname{sgn}(xy)
369 /// \left \lfloor \left | \frac{x}{y} \right | \right \rfloor \right ).
370 /// $$
371 ///
372 /// # Worst-case complexity
373 /// Constant time and additional memory.
374 ///
375 /// # Panics
376 /// Panics if `other` is 0, or if `self` is `$t::MIN` and `other` is -1.
377 ///
378 /// # Examples
379 /// See [here](super::div_mod#div_rem).
380 #[inline]
381 fn div_rem(self, other: $t) -> ($t, $t) {
382 div_rem_signed(self, other)
383 }
384 }
385
386 impl DivAssignRem<$t> for $t {
387 type RemOutput = $t;
388
389 /// Divides a number by another number in place, returning the remainder. The quotient
390 /// is rounded towards zero and the remainder has the same sign as the dividend.
391 ///
392 /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$.
393 ///
394 /// $$
395 /// f(x, y) = x - y \operatorname{sgn}(xy)
396 /// \left \lfloor \left | \frac{x}{y} \right | \right \rfloor,
397 /// $$
398 /// $$
399 /// x \gets \operatorname{sgn}(xy) \left \lfloor \left | \frac{x}{y} \right |
400 /// \right \rfloor.
401 /// $$
402 ///
403 /// # Worst-case complexity
404 /// Constant time and additional memory.
405 ///
406 /// # Panics
407 /// Panics if `other` is 0, or if `self` is `$t::MIN` and `other` is -1.
408 ///
409 /// # Examples
410 /// See [here](super::div_mod#div_assign_rem).
411 #[inline]
412 fn div_assign_rem(&mut self, other: $t) -> $t {
413 div_assign_rem_signed(self, other)
414 }
415 }
416
417 impl CeilingDivMod<$t> for $t {
418 type DivOutput = $t;
419 type ModOutput = $t;
420
421 /// Divides a number by another number, returning the quotient and remainder. The
422 /// quotient is rounded towards positive infinity and the remainder has the opposite
423 /// sign as the second number.
424 ///
425 /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$.
426 ///
427 /// $$
428 /// f(x, y) = \left ( \left \lceil \frac{x}{y} \right \rceil, \space
429 /// x - y\left \lceil \frac{x}{y} \right \rceil \right ).
430 /// $$
431 ///
432 /// # Worst-case complexity
433 /// Constant time and additional memory.
434 ///
435 /// # Panics
436 /// Panics if `other` is 0, or if `self` is `$t::MIN` and `other` is -1.
437 ///
438 /// # Examples
439 /// See [here](super::div_mod#ceiling_div_mod).
440 #[inline]
441 fn ceiling_div_mod(self, other: $t) -> ($t, $t) {
442 ceiling_div_mod_signed(self, other)
443 }
444 }
445
446 impl CeilingDivAssignMod<$t> for $t {
447 type ModOutput = $t;
448
449 /// Divides a number by another number in place, returning the remainder. The quotient
450 /// is rounded towards positive infinity and the remainder has the opposite sign as the
451 /// second number.
452 ///
453 /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$.
454 ///
455 /// $$
456 /// f(x, y) = x - y\left \lceil\frac{x}{y} \right \rceil,
457 /// $$
458 /// $$
459 /// x \gets \left \lceil \frac{x}{y} \right \rceil.
460 /// $$
461 ///
462 /// # Worst-case complexity
463 /// Constant time and additional memory.
464 ///
465 /// # Panics
466 /// Panics if `other` is 0, or if `self` is `$t::MIN` and `other` is -1.
467 ///
468 /// # Examples
469 /// See [here](super::div_mod#ceiling_div_assign_mod).
470 #[inline]
471 fn ceiling_div_assign_mod(&mut self, other: $t) -> $t {
472 let (q, r) = self.ceiling_div_mod(other);
473 *self = q;
474 r
475 }
476 }
477 };
478}
479apply_to_signeds!(impl_div_mod_signed);
480
481// Divides `x` by `d`, given `shift`, the number of leading zeros of `d`, and `d_inv`, the inverse
482// of `d << shift` computed by `limbs_invert_limb`.
483//
484// This is equivalent to `udiv_qrnnd_preinv` from `gmp-impl.h`, GMP 6.2.1, where the dividend
485// occupies a single limb.
486fn div_mod_preinverted<
487 T: PrimitiveUnsigned,
488 DT: From<T> + HasHalf<Half = T> + JoinHalves + PrimitiveUnsigned + SplitInHalf,
489>(
490 x: T,
491 d: T,
492 d_inv: T,
493 shift: u64,
494) -> (T, T) {
495 let d = d << shift;
496 let (y_1, y_0) = if shift == 0 {
497 (T::ZERO, x)
498 } else {
499 (x >> (T::WIDTH - shift), x << shift)
500 };
501 let (q_1, q_0) = (DT::from(d_inv) * DT::from(y_1))
502 .wrapping_add(DT::join_halves(y_1, y_0))
503 .split_in_half();
504 let mut q = q_1.wrapping_add(T::ONE);
505 let mut r = y_0.wrapping_sub(q.wrapping_mul(d));
506 if r > q_0 {
507 q.wrapping_sub_assign(T::ONE);
508 r.wrapping_add_assign(d);
509 }
510 if r >= d {
511 // The generic `udiv_qrnnd_preinv` needs this second adjustment, but with a single-limb
512 // dividend `y_1 < 2^shift <= d`, and the tighter estimate never seems to require it:
513 // exhaustively verified for 8-bit limbs, and never observed in large random 64-bit sweeps.
514 fail_on_untested_path("div_mod_preinverted, second adjustment");
515 q += T::ONE;
516 r -= d;
517 }
518 (q, r >> shift)
519}
520
521macro_rules! impl_div_mod_precomputed_fast {
522 ($t:ident, $dt:ident, $invert_limb:ident) => {
523 impl DivModPrecomputed<$t> for $t {
524 type DivOutput = $t;
525 type ModOutput = $t;
526 type Data = ($t, u64);
527
528 /// Precomputes data for division: the `limbs_invert_limb`-style inverse of the
529 /// normalized divisor, and the normalizing shift. See `div_mod_precomputed` and
530 /// [`div_assign_mod_precomputed`](super::traits::DivAssignModPrecomputed).
531 ///
532 /// # Worst-case complexity
533 /// Constant time and additional memory.
534 ///
535 /// # Panics
536 /// Panics if `other` is 0.
537 ///
538 /// This is equivalent to `n_preinvert_limb` from `ulong_extras.h`, FLINT 2.7.1, with
539 /// the normalizing shift retained, as in FLINT's `nmod_t`.
540 fn precompute_div_mod_data(&other: &$t) -> ($t, u64) {
541 assert_ne!(other, 0, "division by zero");
542 let shift = LeadingZeros::leading_zeros(other);
543 ($invert_limb(other << shift), shift)
544 }
545
546 /// Divides a number by another number, returning the quotient and remainder.
547 ///
548 /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$.
549 ///
550 /// Some precomputed data is provided; this speeds up computations involving several
551 /// divisions by the same divisor. The precomputed data should be obtained using
552 /// [`precompute_div_mod_data`](DivModPrecomputed::precompute_div_mod_data).
553 ///
554 /// # Worst-case complexity
555 /// Constant time and additional memory.
556 ///
557 /// This trades the hardware division for a widening multiplication and adjustments,
558 /// which pays off on processors whose dividers are slow relative to their multipliers;
559 /// on processors with fast, pipelined dividers, plain division may be faster.
560 ///
561 /// # Examples
562 /// See [here](super::div_mod#div_mod_precomputed).
563 ///
564 /// This is equivalent to `udiv_qrnnd_preinv` from `gmp-impl.h`, GMP 6.2.1, where the
565 /// dividend occupies a single limb.
566 #[inline]
567 fn div_mod_precomputed(self, other: $t, data: &($t, u64)) -> ($t, $t) {
568 div_mod_preinverted::<$t, $dt>(self, other, data.0, data.1)
569 }
570 }
571 };
572}
573impl_div_mod_precomputed_fast!(u32, u64, limbs_invert_limb_u32);
574impl_div_mod_precomputed_fast!(u64, u128, limbs_invert_limb_u64);
575
576macro_rules! impl_div_mod_precomputed_promoted {
577 ($t:ident) => {
578 impl DivModPrecomputed<$t> for $t {
579 type DivOutput = $t;
580 type ModOutput = $t;
581 type Data = (u32, u64);
582
583 /// Precomputes data for division. See `div_mod_precomputed` and
584 /// [`div_assign_mod_precomputed`](super::traits::DivAssignModPrecomputed).
585 ///
586 /// # Worst-case complexity
587 /// Constant time and additional memory.
588 ///
589 /// # Panics
590 /// Panics if `other` is 0.
591 ///
592 /// This is equivalent to `n_preinvert_limb` from `ulong_extras.h`, FLINT 2.7.1.
593 fn precompute_div_mod_data(&other: &$t) -> (u32, u64) {
594 u32::precompute_div_mod_data(&u32::from(other))
595 }
596
597 /// Divides a number by another number, returning the quotient and remainder.
598 ///
599 /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$.
600 ///
601 /// Some precomputed data is provided; this speeds up computations involving several
602 /// divisions by the same divisor. The precomputed data should be obtained using
603 /// [`precompute_div_mod_data`](DivModPrecomputed::precompute_div_mod_data).
604 ///
605 /// # Worst-case complexity
606 /// Constant time and additional memory.
607 ///
608 /// # Examples
609 /// See [here](super::div_mod#div_mod_precomputed).
610 #[inline]
611 fn div_mod_precomputed(self, other: $t, data: &(u32, u64)) -> ($t, $t) {
612 let (q, r) = u32::from(self).div_mod_precomputed(u32::from(other), data);
613 ($t::wrapping_from(q), $t::wrapping_from(r))
614 }
615 }
616 };
617}
618impl_div_mod_precomputed_promoted!(u8);
619impl_div_mod_precomputed_promoted!(u16);
620
621impl DivModPrecomputed<Self> for u128 {
622 type DivOutput = Self;
623 type ModOutput = Self;
624 type Data = ();
625
626 /// Precomputes data for division. See `div_mod_precomputed` and
627 /// [`div_assign_mod_precomputed`](super::traits::DivAssignModPrecomputed).
628 ///
629 /// # Worst-case complexity
630 /// Constant time and additional memory.
631 ///
632 /// # Panics
633 /// Panics if `other` is 0.
634 fn precompute_div_mod_data(&other: &Self) {
635 assert_ne!(other, 0, "division by zero");
636 }
637
638 /// Divides a number by another number, returning the quotient and remainder.
639 ///
640 /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$.
641 ///
642 /// Some precomputed data is provided; this speeds up computations involving several divisions
643 /// by the same divisor. The precomputed data should be obtained using
644 /// [`precompute_div_mod_data`](DivModPrecomputed::precompute_div_mod_data).
645 ///
646 /// # Worst-case complexity
647 /// Constant time and additional memory.
648 ///
649 /// # Panics
650 /// Panics if `other` is 0.
651 ///
652 /// # Examples
653 /// See [here](super::div_mod#div_mod_precomputed).
654 #[inline]
655 fn div_mod_precomputed(self, other: Self, _data: &()) -> (Self, Self) {
656 self.div_mod(other)
657 }
658}
659
660impl DivModPrecomputed<Self> for usize {
661 type DivOutput = Self;
662 type ModOutput = Self;
663 type Data = (Self, u64);
664
665 /// Precomputes data for division. See `div_mod_precomputed` and
666 /// [`div_assign_mod_precomputed`](super::traits::DivAssignModPrecomputed).
667 ///
668 /// # Worst-case complexity
669 /// Constant time and additional memory.
670 ///
671 /// # Panics
672 /// Panics if `other` is 0.
673 ///
674 /// This is equivalent to `n_preinvert_limb` from `ulong_extras.h`, FLINT 2.7.1.
675 fn precompute_div_mod_data(&other: &Self) -> (Self, u64) {
676 if USIZE_IS_U32 {
677 let (d_inv, shift) = u32::precompute_div_mod_data(&u32::wrapping_from(other));
678 (Self::wrapping_from(d_inv), shift)
679 } else {
680 let (d_inv, shift) = u64::precompute_div_mod_data(&u64::wrapping_from(other));
681 (Self::wrapping_from(d_inv), shift)
682 }
683 }
684
685 /// Divides a number by another number, returning the quotient and remainder.
686 ///
687 /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$.
688 ///
689 /// Some precomputed data is provided; this speeds up computations involving several divisions
690 /// by the same divisor. The precomputed data should be obtained using
691 /// [`precompute_div_mod_data`](DivModPrecomputed::precompute_div_mod_data).
692 ///
693 /// # Worst-case complexity
694 /// Constant time and additional memory.
695 ///
696 /// # Examples
697 /// See [here](super::div_mod#div_mod_precomputed).
698 fn div_mod_precomputed(self, other: Self, data: &(Self, u64)) -> (Self, Self) {
699 if USIZE_IS_U32 {
700 let (q, r) = u32::wrapping_from(self).div_mod_precomputed(
701 u32::wrapping_from(other),
702 &(u32::wrapping_from(data.0), data.1),
703 );
704 (Self::wrapping_from(q), Self::wrapping_from(r))
705 } else {
706 let (q, r) = u64::wrapping_from(self).div_mod_precomputed(
707 u64::wrapping_from(other),
708 &(u64::wrapping_from(data.0), data.1),
709 );
710 (Self::wrapping_from(q), Self::wrapping_from(r))
711 }
712 }
713}
714
715// The remainder is with respect to the ceiling quotient: `x = qy - r` and `0 <= r < y`.
716fn ceiling_div_neg_mod_precomputed_unsigned<
717 U: PrimitiveUnsigned + DivModPrecomputed<U, DivOutput = U, ModOutput = U>,
718>(
719 x: U,
720 other: U,
721 data: &<U as DivModPrecomputed<U>>::Data,
722) -> (U, U) {
723 let (quotient, remainder) = x.div_mod_precomputed(other, data);
724 if remainder == U::ZERO {
725 (quotient, U::ZERO)
726 } else {
727 // Here remainder != 0, so other > 1, so quotient < U::MAX.
728 (quotient + U::ONE, other - remainder)
729 }
730}
731
732fn div_mod_precomputed_signed<
733 U: PrimitiveUnsigned + DivModPrecomputed<U, DivOutput = U, ModOutput = U>,
734 S: PrimitiveSigned + ExactFrom<U> + UnsignedAbs<Output = U> + WrappingFrom<U>,
735>(
736 x: S,
737 other: S,
738 data: &<U as DivModPrecomputed<U>>::Data,
739) -> (S, S) {
740 let (quotient, remainder) = if (x >= S::ZERO) == (other >= S::ZERO) {
741 let (quotient, remainder) = x
742 .unsigned_abs()
743 .div_mod_precomputed(other.unsigned_abs(), data);
744 (S::exact_from(quotient), remainder)
745 } else {
746 let (quotient, remainder) =
747 ceiling_div_neg_mod_precomputed_unsigned(x.unsigned_abs(), other.unsigned_abs(), data);
748 (S::wrapping_from(quotient).wrapping_neg(), remainder)
749 };
750 (
751 quotient,
752 if other >= S::ZERO {
753 S::exact_from(remainder)
754 } else {
755 -S::exact_from(remainder)
756 },
757 )
758}
759
760macro_rules! impl_div_mod_precomputed_signed {
761 ($u:ident, $t:ident) => {
762 impl DivModPrecomputed<$t> for $t {
763 type DivOutput = $t;
764 type ModOutput = $t;
765 type Data = <$u as DivModPrecomputed<$u>>::Data;
766
767 /// Precomputes data for division. See `div_mod_precomputed` and
768 /// [`div_assign_mod_precomputed`](super::traits::DivAssignModPrecomputed).
769 ///
770 /// The data depends only on the absolute value of the divisor.
771 ///
772 /// # Worst-case complexity
773 /// Constant time and additional memory.
774 ///
775 /// # Panics
776 /// Panics if `other` is 0.
777 #[inline]
778 fn precompute_div_mod_data(&other: &$t) -> Self::Data {
779 $u::precompute_div_mod_data(&other.unsigned_abs())
780 }
781
782 /// Divides a number by another number, returning the quotient and remainder. The
783 /// quotient is rounded towards negative infinity, and the remainder has the same sign
784 /// as the second number.
785 ///
786 /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$.
787 ///
788 /// Some precomputed data is provided; this speeds up computations involving several
789 /// divisions by the same divisor. The precomputed data should be obtained using
790 /// [`precompute_div_mod_data`](DivModPrecomputed::precompute_div_mod_data).
791 ///
792 /// # Worst-case complexity
793 /// Constant time and additional memory.
794 ///
795 /// # Panics
796 /// Panics if `self` is `$t::MIN` and `other` is -1.
797 ///
798 /// # Examples
799 /// See [here](super::div_mod#div_mod_precomputed).
800 #[inline]
801 fn div_mod_precomputed(self, other: $t, data: &Self::Data) -> ($t, $t) {
802 div_mod_precomputed_signed::<$u, $t>(self, other, data)
803 }
804 }
805 };
806}
807apply_to_unsigned_signed_pairs!(impl_div_mod_precomputed_signed);
808
809macro_rules! impl_div_assign_mod_precomputed {
810 ($t:ident) => {
811 impl DivAssignModPrecomputed<$t> for $t {
812 /// Divides a number by another number in place, returning the remainder. The quotient
813 /// is rounded towards negative infinity, and the remainder has the same sign as the
814 /// second number.
815 ///
816 /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$.
817 ///
818 /// Some precomputed data is provided; this speeds up computations involving several
819 /// divisions by the same divisor. The precomputed data should be obtained using
820 /// [`precompute_div_mod_data`](DivModPrecomputed::precompute_div_mod_data).
821 ///
822 /// # Worst-case complexity
823 /// Constant time and additional memory.
824 ///
825 /// # Examples
826 /// See [here](super::div_mod#div_assign_mod_precomputed).
827 #[inline]
828 fn div_assign_mod_precomputed(&mut self, other: $t, data: &Self::Data) -> $t {
829 let (q, r) = self.div_mod_precomputed(other, data);
830 *self = q;
831 r
832 }
833 }
834 };
835}
836apply_to_primitive_ints!(impl_div_assign_mod_precomputed);