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