Skip to main content

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);