malachite_base/num/arithmetic/
div_mod.rs

1// Copyright © 2025 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::num::arithmetic::traits::{
10    CeilingDivAssignMod, CeilingDivAssignNegMod, CeilingDivMod, CeilingDivNegMod, DivAssignMod,
11    DivAssignRem, DivMod, DivRem, UnsignedAbs,
12};
13use crate::num::basic::signeds::PrimitiveSigned;
14use crate::num::basic::unsigneds::PrimitiveUnsigned;
15use crate::num::conversion::traits::{ExactFrom, WrappingFrom};
16
17fn div_mod_unsigned<T: PrimitiveUnsigned>(x: T, other: T) -> (T, T) {
18    let q = x / other;
19    (q, x - q * other)
20}
21
22fn div_assign_mod_unsigned<T: PrimitiveUnsigned>(x: &mut T, other: T) -> T {
23    let original = *x;
24    *x /= other;
25    original - *x * other
26}
27
28fn ceiling_div_neg_mod_unsigned<T: PrimitiveUnsigned>(x: T, other: T) -> (T, T) {
29    let (quotient, remainder) = x.div_mod(other);
30    if remainder == T::ZERO {
31        (quotient, T::ZERO)
32    } else {
33        // Here remainder != 0, so other > 1, so quotient < T::MAX.
34        (quotient + T::ONE, other - remainder)
35    }
36}
37
38fn ceiling_div_assign_neg_mod_unsigned<T: PrimitiveUnsigned>(x: &mut T, other: T) -> T {
39    let remainder = x.div_assign_mod(other);
40    if remainder == T::ZERO {
41        T::ZERO
42    } else {
43        // Here remainder != 0, so other > 1, so self < T::MAX.
44        *x += T::ONE;
45        other - remainder
46    }
47}
48
49macro_rules! impl_div_mod_unsigned {
50    ($t:ident) => {
51        impl DivMod<$t> for $t {
52            type DivOutput = $t;
53            type ModOutput = $t;
54
55            /// Divides a number by another number, returning the quotient and remainder. The
56            /// quotient is rounded towards negative infinity.
57            ///
58            /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$.
59            ///
60            /// $$
61            /// f(x, y) = \left ( \left \lfloor \frac{x}{y} \right \rfloor, \space
62            /// x - y\left \lfloor \frac{x}{y} \right \rfloor \right ).
63            /// $$
64            ///
65            /// # Worst-case complexity
66            /// Constant time and additional memory.
67            ///
68            /// # Panics
69            /// Panics if `other` is 0.
70            ///
71            /// # Examples
72            /// See [here](super::div_mod#div_mod).
73            #[inline]
74            fn div_mod(self, other: $t) -> ($t, $t) {
75                div_mod_unsigned(self, other)
76            }
77        }
78
79        impl DivAssignMod<$t> for $t {
80            type ModOutput = $t;
81
82            /// Divides a number by another number in place, returning the remainder. The quotient
83            /// is rounded towards negative infinity.
84            ///
85            /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$.
86            ///
87            /// $$
88            /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor,
89            /// $$
90            /// $$
91            /// x \gets \left \lfloor \frac{x}{y} \right \rfloor.
92            /// $$
93            ///
94            /// # Worst-case complexity
95            /// Constant time and additional memory.
96            ///
97            /// # Panics
98            /// Panics if `other` is 0.
99            ///
100            /// # Examples
101            /// See [here](super::div_mod#div_assign_mod).
102            #[inline]
103            fn div_assign_mod(&mut self, other: $t) -> $t {
104                div_assign_mod_unsigned(self, other)
105            }
106        }
107
108        impl DivRem<$t> for $t {
109            type DivOutput = $t;
110            type RemOutput = $t;
111
112            /// Divides a number by another number, returning the quotient and remainder. The
113            /// quotient is rounded towards zero.
114            ///
115            /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$.
116            ///
117            /// $$
118            /// f(x, y) = \left ( \left \lfloor \frac{x}{y} \right \rfloor, \space
119            /// x - y\left \lfloor \frac{x}{y} \right \rfloor \right ).
120            /// $$
121            ///
122            /// For unsigned integers, `div_rem` is equivalent to `div_mod`.
123            ///
124            /// # Worst-case complexity
125            /// Constant time and additional memory.
126            ///
127            /// # Panics
128            /// Panics if `other` is 0.
129            ///
130            /// # Examples
131            /// See [here](super::div_mod#div_rem).
132            #[inline]
133            fn div_rem(self, other: $t) -> ($t, $t) {
134                self.div_mod(other)
135            }
136        }
137
138        impl DivAssignRem<$t> for $t {
139            type RemOutput = $t;
140
141            /// Divides a number by another number in place, returning the remainder. The quotient
142            /// is rounded towards zero.
143            ///
144            /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq r < y$.
145            ///
146            /// $$
147            /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor,
148            /// $$
149            /// $$
150            /// x \gets \left \lfloor \frac{x}{y} \right \rfloor.
151            /// $$
152            ///
153            /// For unsigned integers, `div_assign_rem` is equivalent to `div_assign_mod`.
154            ///
155            /// # Worst-case complexity
156            /// Constant time and additional memory.
157            ///
158            /// # Panics
159            /// Panics if `other` is 0.
160            ///
161            /// # Examples
162            /// See [here](super::div_mod#div_assign_rem).
163            #[inline]
164            fn div_assign_rem(&mut self, other: $t) -> $t {
165                self.div_assign_mod(other)
166            }
167        }
168
169        impl CeilingDivNegMod<$t> for $t {
170            type DivOutput = $t;
171            type ModOutput = $t;
172
173            /// Divides a number by another number, returning the ceiling of the quotient and the
174            /// remainder of the negative of the first number divided by the second.
175            ///
176            /// The quotient and remainder satisfy $x = qy - r$ and $0 \leq r < y$.
177            ///
178            /// $$
179            /// f(x, y) = \left ( \left \lceil \frac{x}{y} \right \rceil, \space
180            /// y\left \lceil \frac{x}{y} \right \rceil - x \right ).
181            /// $$
182            ///
183            /// # Worst-case complexity
184            /// Constant time and additional memory.
185            ///
186            /// # Panics
187            /// Panics if `other` is 0.
188            ///
189            /// # Examples
190            /// See [here](super::div_mod#ceiling_div_neg_mod).
191            #[inline]
192            fn ceiling_div_neg_mod(self, other: $t) -> ($t, $t) {
193                ceiling_div_neg_mod_unsigned(self, other)
194            }
195        }
196
197        impl CeilingDivAssignNegMod<$t> for $t {
198            type ModOutput = $t;
199
200            /// Divides a number by another number in place, returning the remainder of the negative
201            /// of the first number divided by the second.
202            ///
203            /// The quotient and remainder satisfy $x = qy - r$ and $0 \leq r < y$.
204            ///
205            /// $$
206            /// f(x, y) = y\left \lceil \frac{x}{y} \right \rceil - x,
207            /// $$
208            /// $$
209            /// x \gets \left \lceil \frac{x}{y} \right \rceil.
210            /// $$
211            ///
212            /// # Worst-case complexity
213            /// Constant time and additional memory.
214            ///
215            /// # Panics
216            /// Panics if `other` is 0.
217            ///
218            /// # Examples
219            /// See [here](super::div_mod#ceiling_div_assign_neg_mod).
220            #[inline]
221            fn ceiling_div_assign_neg_mod(&mut self, other: $t) -> $t {
222                ceiling_div_assign_neg_mod_unsigned(self, other)
223            }
224        }
225    };
226}
227apply_to_unsigneds!(impl_div_mod_unsigned);
228
229fn div_mod_signed<
230    U: PrimitiveUnsigned,
231    S: PrimitiveSigned + ExactFrom<U> + UnsignedAbs<Output = U> + WrappingFrom<U>,
232>(
233    x: S,
234    other: S,
235) -> (S, S) {
236    let (quotient, remainder) = if (x >= S::ZERO) == (other >= S::ZERO) {
237        let (quotient, remainder) = x.unsigned_abs().div_mod(other.unsigned_abs());
238        (S::exact_from(quotient), remainder)
239    } else {
240        let (quotient, remainder) = x.unsigned_abs().ceiling_div_neg_mod(other.unsigned_abs());
241        (S::wrapping_from(quotient).wrapping_neg(), remainder)
242    };
243    (
244        quotient,
245        if other >= S::ZERO {
246            S::exact_from(remainder)
247        } else {
248            -S::exact_from(remainder)
249        },
250    )
251}
252
253fn div_rem_signed<T: PrimitiveSigned>(x: T, other: T) -> (T, T) {
254    let q = x.checked_div(other).unwrap();
255    (q, x - q * other)
256}
257
258fn div_assign_rem_signed<T: PrimitiveSigned>(x: &mut T, other: T) -> T {
259    let original = *x;
260    *x = x.checked_div(other).unwrap();
261    original - *x * other
262}
263
264fn ceiling_div_mod_signed<
265    U: PrimitiveUnsigned,
266    T: PrimitiveSigned + ExactFrom<U> + UnsignedAbs<Output = U> + WrappingFrom<U>,
267>(
268    x: T,
269    other: T,
270) -> (T, T) {
271    let (quotient, remainder) = if (x >= T::ZERO) == (other >= T::ZERO) {
272        let (quotient, remainder) = x.unsigned_abs().ceiling_div_neg_mod(other.unsigned_abs());
273        (T::exact_from(quotient), remainder)
274    } else {
275        let (quotient, remainder) = x.unsigned_abs().div_mod(other.unsigned_abs());
276        (T::wrapping_from(quotient).wrapping_neg(), remainder)
277    };
278    (
279        quotient,
280        if other >= T::ZERO {
281            -T::exact_from(remainder)
282        } else {
283            T::exact_from(remainder)
284        },
285    )
286}
287
288macro_rules! impl_div_mod_signed {
289    ($t:ident) => {
290        impl DivMod<$t> for $t {
291            type DivOutput = $t;
292            type ModOutput = $t;
293
294            /// Divides a number by another number, returning the quotient and remainder. The
295            /// quotient is rounded towards negative infinity, and the remainder has the same sign
296            /// as the second number.
297            ///
298            /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$.
299            ///
300            /// $$
301            /// f(x, y) = \left ( \left \lfloor \frac{x}{y} \right \rfloor, \space
302            /// x - y\left \lfloor \frac{x}{y} \right \rfloor \right ).
303            /// $$
304            ///
305            /// # Worst-case complexity
306            /// Constant time and additional memory.
307            ///
308            /// # Panics
309            /// Panics if `other` is 0, or if `self` is `$t::MIN` and `other` is -1.
310            ///
311            /// # Examples
312            /// See [here](super::div_mod#div_mod).
313            #[inline]
314            fn div_mod(self, other: $t) -> ($t, $t) {
315                div_mod_signed(self, other)
316            }
317        }
318
319        impl DivAssignMod<$t> for $t {
320            type ModOutput = $t;
321
322            /// Divides a number by another number in place, returning the remainder. The quotient
323            /// is rounded towards negative infinity, and the remainder has the same sign as the
324            /// second number.
325            ///
326            /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$.
327            ///
328            /// $$
329            /// f(x, y) = x - y\left \lfloor \frac{x}{y} \right \rfloor,
330            /// $$
331            /// $$
332            /// x \gets \left \lfloor \frac{x}{y} \right \rfloor.
333            /// $$
334            ///
335            /// # Worst-case complexity
336            /// Constant time and additional memory.
337            ///
338            /// # Panics
339            /// Panics if `other` is 0, or if `self` is `$t::MIN` and `other` is -1.
340            ///
341            /// # Examples
342            /// See [here](super::div_mod#div_assign_mod).
343            #[inline]
344            fn div_assign_mod(&mut self, other: $t) -> $t {
345                let (q, r) = self.div_mod(other);
346                *self = q;
347                r
348            }
349        }
350
351        impl DivRem<$t> for $t {
352            type DivOutput = $t;
353            type RemOutput = $t;
354
355            /// Divides a number by another number, returning the quotient and remainder. The
356            /// quotient is rounded towards zero and the remainder has the same sign as the
357            /// dividend.
358            ///
359            /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$.
360            ///
361            /// $$
362            /// f(x, y) = \left ( \operatorname{sgn}(xy) \left \lfloor \left | \frac{x}{y} \right |
363            /// \right \rfloor, \space
364            /// x - y \operatorname{sgn}(xy)
365            /// \left \lfloor \left | \frac{x}{y} \right | \right \rfloor \right ).
366            /// $$
367            ///
368            /// # Worst-case complexity
369            /// Constant time and additional memory.
370            ///
371            /// # Panics
372            /// Panics if `other` is 0, or if `self` is `$t::MIN` and `other` is -1.
373            ///
374            /// # Examples
375            /// See [here](super::div_mod#div_rem).
376            #[inline]
377            fn div_rem(self, other: $t) -> ($t, $t) {
378                div_rem_signed(self, other)
379            }
380        }
381
382        impl DivAssignRem<$t> for $t {
383            type RemOutput = $t;
384
385            /// Divides a number by another number in place, returning the remainder. The quotient
386            /// is rounded towards zero and the remainder has the same sign as the dividend.
387            ///
388            /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$.
389            ///
390            /// $$
391            /// f(x, y) = x - y \operatorname{sgn}(xy)
392            /// \left \lfloor \left | \frac{x}{y} \right | \right \rfloor,
393            /// $$
394            /// $$
395            /// x \gets \operatorname{sgn}(xy) \left \lfloor \left | \frac{x}{y} \right |
396            /// \right \rfloor.
397            /// $$
398            ///
399            /// # Worst-case complexity
400            /// Constant time and additional memory.
401            ///
402            /// # Panics
403            /// Panics if `other` is 0, or if `self` is `$t::MIN` and `other` is -1.
404            ///
405            /// # Examples
406            /// See [here](super::div_mod#div_assign_rem).
407            #[inline]
408            fn div_assign_rem(&mut self, other: $t) -> $t {
409                div_assign_rem_signed(self, other)
410            }
411        }
412
413        impl CeilingDivMod<$t> for $t {
414            type DivOutput = $t;
415            type ModOutput = $t;
416
417            /// Divides a number by another number, returning the quotient and remainder. The
418            /// quotient is rounded towards positive infinity and the remainder has the opposite
419            /// sign as the second number.
420            ///
421            /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$.
422            ///
423            /// $$
424            /// f(x, y) = \left ( \left \lceil \frac{x}{y} \right \rceil, \space
425            /// x - y\left \lceil \frac{x}{y} \right \rceil \right ).
426            /// $$
427            ///
428            /// # Worst-case complexity
429            /// Constant time and additional memory.
430            ///
431            /// # Panics
432            /// Panics if `other` is 0, or if `self` is `$t::MIN` and `other` is -1.
433            ///
434            /// # Examples
435            /// See [here](super::div_mod#ceiling_div_mod).
436            #[inline]
437            fn ceiling_div_mod(self, other: $t) -> ($t, $t) {
438                ceiling_div_mod_signed(self, other)
439            }
440        }
441
442        impl CeilingDivAssignMod<$t> for $t {
443            type ModOutput = $t;
444
445            /// Divides a number by another number in place, returning the remainder. The quotient
446            /// is rounded towards positive infinity and the remainder has the opposite sign as the
447            /// second number.
448            ///
449            /// The quotient and remainder satisfy $x = qy + r$ and $0 \leq |r| < |y|$.
450            ///
451            /// $$
452            /// f(x, y) = x - y\left \lceil\frac{x}{y} \right \rceil,
453            /// $$
454            /// $$
455            /// x \gets \left \lceil \frac{x}{y} \right \rceil.
456            /// $$
457            ///
458            /// # Worst-case complexity
459            /// Constant time and additional memory.
460            ///
461            /// # Panics
462            /// Panics if `other` is 0, or if `self` is `$t::MIN` and `other` is -1.
463            ///
464            /// # Examples
465            /// See [here](super::div_mod#ceiling_div_assign_mod).
466            #[inline]
467            fn ceiling_div_assign_mod(&mut self, other: $t) -> $t {
468                let (q, r) = self.ceiling_div_mod(other);
469                *self = q;
470                r
471            }
472        }
473    };
474}
475apply_to_signeds!(impl_div_mod_signed);