malachite_nz/integer/arithmetic/
round_to_multiple.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::integer::Integer;
10use core::cmp::Ordering;
11use malachite_base::num::arithmetic::traits::{RoundToMultiple, RoundToMultipleAssign};
12use malachite_base::rounding_modes::RoundingMode;
13
14impl RoundToMultiple<Self> for Integer {
15    type Output = Self;
16
17    /// Rounds an [`Integer`] to a multiple of another [`Integer`], according to a specified
18    /// rounding mode. Both [`Integer`]s are taken by value. An [`Ordering`] is also returned,
19    /// indicating whether the returned value is less than, equal to, or greater than the original
20    /// value.
21    ///
22    /// Let $q = \frac{x}{|y|}$:
23    ///
24    /// $f(x, y, \mathrm{Down}) =  \operatorname{sgn}(q) |y| \lfloor |q| \rfloor.$
25    ///
26    /// $f(x, y, \mathrm{Up}) = \operatorname{sgn}(q) |y| \lceil |q| \rceil.$
27    ///
28    /// $f(x, y, \mathrm{Floor}) = |y| \lfloor q \rfloor.$
29    ///
30    /// $f(x, y, \mathrm{Ceiling}) = |y| \lceil q \rceil.$
31    ///
32    /// $$
33    /// f(x, y, \mathrm{Nearest}) = \begin{cases}
34    ///     y \lfloor q \rfloor & \text{if} \\quad
35    ///         q - \lfloor q \rfloor < \frac{1}{2} \\\\
36    ///     y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\
37    ///     y \lfloor q \rfloor &
38    ///     \text{if} \\quad q - \lfloor q \rfloor =
39    ///         \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor
40    ///     \\ \text{is even} \\\\
41    ///     y \lceil q \rceil &
42    ///     \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2}
43    ///         \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.}
44    /// \end{cases}
45    /// $$
46    ///
47    /// $f(x, y, \mathrm{Exact}) = q$, but panics if $q \notin \Z$.
48    ///
49    /// The following two expressions are equivalent:
50    /// - `x.round_to_multiple(other, Exact)`
51    /// - `{ assert!(x.divisible_by(other)); x }`
52    ///
53    /// but the latter should be used as it is clearer and more efficient.
54    ///
55    /// # Worst-case complexity
56    /// $T(n) = O(n \log n \log\log n)$
57    ///
58    /// $M(n) = O(n \log n)$
59    ///
60    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
61    ///
62    /// # Panics
63    /// - If `rm` is `Exact`, but `self` is not a multiple of `other`.
64    /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero.
65    ///
66    /// # Examples
67    /// ```
68    /// use malachite_base::num::arithmetic::traits::RoundToMultiple;
69    /// use malachite_base::num::basic::traits::Zero;
70    /// use malachite_base::rounding_modes::RoundingMode::*;
71    /// use malachite_base::strings::ToDebugString;
72    /// use malachite_nz::integer::Integer;
73    ///
74    /// assert_eq!(
75    ///     Integer::from(-5)
76    ///         .round_to_multiple(Integer::ZERO, Down)
77    ///         .to_debug_string(),
78    ///     "(0, Greater)"
79    /// );
80    ///
81    /// assert_eq!(
82    ///     Integer::from(-10)
83    ///         .round_to_multiple(Integer::from(4), Down)
84    ///         .to_debug_string(),
85    ///     "(-8, Greater)"
86    /// );
87    /// assert_eq!(
88    ///     Integer::from(-10)
89    ///         .round_to_multiple(Integer::from(4), Up)
90    ///         .to_debug_string(),
91    ///     "(-12, Less)"
92    /// );
93    /// assert_eq!(
94    ///     Integer::from(-10)
95    ///         .round_to_multiple(Integer::from(5), Exact)
96    ///         .to_debug_string(),
97    ///     "(-10, Equal)"
98    /// );
99    /// assert_eq!(
100    ///     Integer::from(-10)
101    ///         .round_to_multiple(Integer::from(3), Nearest)
102    ///         .to_debug_string(),
103    ///     "(-9, Greater)"
104    /// );
105    /// assert_eq!(
106    ///     Integer::from(-20)
107    ///         .round_to_multiple(Integer::from(3), Nearest)
108    ///         .to_debug_string(),
109    ///     "(-21, Less)"
110    /// );
111    /// assert_eq!(
112    ///     Integer::from(-10)
113    ///         .round_to_multiple(Integer::from(4), Nearest)
114    ///         .to_debug_string(),
115    ///     "(-8, Greater)"
116    /// );
117    /// assert_eq!(
118    ///     Integer::from(-14)
119    ///         .round_to_multiple(Integer::from(4), Nearest)
120    ///         .to_debug_string(),
121    ///     "(-16, Less)"
122    /// );
123    ///
124    /// assert_eq!(
125    ///     Integer::from(-10)
126    ///         .round_to_multiple(Integer::from(-4), Down)
127    ///         .to_debug_string(),
128    ///     "(-8, Greater)"
129    /// );
130    /// assert_eq!(
131    ///     Integer::from(-10)
132    ///         .round_to_multiple(Integer::from(-4), Up)
133    ///         .to_debug_string(),
134    ///     "(-12, Less)"
135    /// );
136    /// assert_eq!(
137    ///     Integer::from(-10)
138    ///         .round_to_multiple(Integer::from(-5), Exact)
139    ///         .to_debug_string(),
140    ///     "(-10, Equal)"
141    /// );
142    /// assert_eq!(
143    ///     Integer::from(-10)
144    ///         .round_to_multiple(Integer::from(-3), Nearest)
145    ///         .to_debug_string(),
146    ///     "(-9, Greater)"
147    /// );
148    /// assert_eq!(
149    ///     Integer::from(-20)
150    ///         .round_to_multiple(Integer::from(-3), Nearest)
151    ///         .to_debug_string(),
152    ///     "(-21, Less)"
153    /// );
154    /// assert_eq!(
155    ///     Integer::from(-10)
156    ///         .round_to_multiple(Integer::from(-4), Nearest)
157    ///         .to_debug_string(),
158    ///     "(-8, Greater)"
159    /// );
160    /// assert_eq!(
161    ///     Integer::from(-14)
162    ///         .round_to_multiple(Integer::from(-4), Nearest)
163    ///         .to_debug_string(),
164    ///     "(-16, Less)"
165    /// );
166    /// ```
167    #[inline]
168    fn round_to_multiple(mut self, other: Self, rm: RoundingMode) -> (Self, Ordering) {
169        let o = self.round_to_multiple_assign(other, rm);
170        (self, o)
171    }
172}
173
174impl RoundToMultiple<&Self> for Integer {
175    type Output = Self;
176
177    /// Rounds an [`Integer`] to a multiple of another [`Integer`], according to a specified
178    /// rounding mode. The first [`Integer`] is taken by value and the second by reference. An
179    /// [`Ordering`] is also returned, indicating whether the returned value is less than, equal to,
180    /// or greater than the original value.
181    ///
182    /// Let $q = \frac{x}{|y|}$:
183    ///
184    /// $f(x, y, \mathrm{Down}) =  \operatorname{sgn}(q) |y| \lfloor |q| \rfloor.$
185    ///
186    /// $f(x, y, \mathrm{Up}) = \operatorname{sgn}(q) |y| \lceil |q| \rceil.$
187    ///
188    /// $f(x, y, \mathrm{Floor}) = |y| \lfloor q \rfloor.$
189    ///
190    /// $f(x, y, \mathrm{Ceiling}) = |y| \lceil q \rceil.$
191    ///
192    /// $$
193    /// f(x, y, \mathrm{Nearest}) = \begin{cases}
194    ///     y \lfloor q \rfloor & \text{if} \\quad
195    ///         q - \lfloor q \rfloor < \frac{1}{2} \\\\
196    ///     y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\
197    ///     y \lfloor q \rfloor &
198    ///     \text{if} \\quad q - \lfloor q \rfloor =
199    ///         \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor
200    ///     \\ \text{is even} \\\\
201    ///     y \lceil q \rceil &
202    ///     \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2}
203    ///         \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.}
204    /// \end{cases}
205    /// $$
206    ///
207    /// $f(x, y, \mathrm{Exact}) = q$, but panics if $q \notin \Z$.
208    ///
209    /// The following two expressions are equivalent:
210    /// - `x.round_to_multiple(other, Exact)`
211    /// - `{ assert!(x.divisible_by(other)); x }`
212    ///
213    /// but the latter should be used as it is clearer and more efficient.
214    ///
215    /// # Worst-case complexity
216    /// $T(n) = O(n \log n \log\log n)$
217    ///
218    /// $M(n) = O(n \log n)$
219    ///
220    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
221    ///
222    /// # Panics
223    /// - If `rm` is `Exact`, but `self` is not a multiple of `other`.
224    /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero.
225    ///
226    /// # Examples
227    /// ```
228    /// use malachite_base::num::arithmetic::traits::RoundToMultiple;
229    /// use malachite_base::num::basic::traits::Zero;
230    /// use malachite_base::rounding_modes::RoundingMode::*;
231    /// use malachite_base::strings::ToDebugString;
232    /// use malachite_nz::integer::Integer;
233    ///
234    /// assert_eq!(
235    ///     Integer::from(-5)
236    ///         .round_to_multiple(&Integer::ZERO, Down)
237    ///         .to_debug_string(),
238    ///     "(0, Greater)"
239    /// );
240    ///
241    /// assert_eq!(
242    ///     Integer::from(-10)
243    ///         .round_to_multiple(&Integer::from(4), Down)
244    ///         .to_debug_string(),
245    ///     "(-8, Greater)"
246    /// );
247    /// assert_eq!(
248    ///     Integer::from(-10)
249    ///         .round_to_multiple(&Integer::from(4), Up)
250    ///         .to_debug_string(),
251    ///     "(-12, Less)"
252    /// );
253    /// assert_eq!(
254    ///     Integer::from(-10)
255    ///         .round_to_multiple(&Integer::from(5), Exact)
256    ///         .to_debug_string(),
257    ///     "(-10, Equal)"
258    /// );
259    /// assert_eq!(
260    ///     Integer::from(-10)
261    ///         .round_to_multiple(&Integer::from(3), Nearest)
262    ///         .to_debug_string(),
263    ///     "(-9, Greater)"
264    /// );
265    /// assert_eq!(
266    ///     Integer::from(-20)
267    ///         .round_to_multiple(&Integer::from(3), Nearest)
268    ///         .to_debug_string(),
269    ///     "(-21, Less)"
270    /// );
271    /// assert_eq!(
272    ///     Integer::from(-10)
273    ///         .round_to_multiple(&Integer::from(4), Nearest)
274    ///         .to_debug_string(),
275    ///     "(-8, Greater)"
276    /// );
277    /// assert_eq!(
278    ///     Integer::from(-14)
279    ///         .round_to_multiple(&Integer::from(4), Nearest)
280    ///         .to_debug_string(),
281    ///     "(-16, Less)"
282    /// );
283    ///
284    /// assert_eq!(
285    ///     Integer::from(-10)
286    ///         .round_to_multiple(&Integer::from(-4), Down)
287    ///         .to_debug_string(),
288    ///     "(-8, Greater)"
289    /// );
290    /// assert_eq!(
291    ///     Integer::from(-10)
292    ///         .round_to_multiple(&Integer::from(-4), Up)
293    ///         .to_debug_string(),
294    ///     "(-12, Less)"
295    /// );
296    /// assert_eq!(
297    ///     Integer::from(-10)
298    ///         .round_to_multiple(&Integer::from(-5), Exact)
299    ///         .to_debug_string(),
300    ///     "(-10, Equal)"
301    /// );
302    /// assert_eq!(
303    ///     Integer::from(-10)
304    ///         .round_to_multiple(&Integer::from(-3), Nearest)
305    ///         .to_debug_string(),
306    ///     "(-9, Greater)"
307    /// );
308    /// assert_eq!(
309    ///     Integer::from(-20)
310    ///         .round_to_multiple(&Integer::from(-3), Nearest)
311    ///         .to_debug_string(),
312    ///     "(-21, Less)"
313    /// );
314    /// assert_eq!(
315    ///     Integer::from(-10)
316    ///         .round_to_multiple(&Integer::from(-4), Nearest)
317    ///         .to_debug_string(),
318    ///     "(-8, Greater)"
319    /// );
320    /// assert_eq!(
321    ///     Integer::from(-14)
322    ///         .round_to_multiple(&Integer::from(-4), Nearest)
323    ///         .to_debug_string(),
324    ///     "(-16, Less)"
325    /// );
326    /// ```
327    #[inline]
328    fn round_to_multiple(mut self, other: &Self, rm: RoundingMode) -> (Self, Ordering) {
329        let o = self.round_to_multiple_assign(other, rm);
330        (self, o)
331    }
332}
333
334impl RoundToMultiple<Integer> for &Integer {
335    type Output = Integer;
336
337    /// Rounds an [`Integer`] to a multiple of another [`Integer`], according to a specified
338    /// rounding mode. The first [`Integer`] is taken by reference and the second by value. An
339    /// [`Ordering`] is also returned, indicating whether the returned value is less than, equal to,
340    /// or greater than the original value.
341    ///
342    /// Let $q = \frac{x}{|y|}$:
343    ///
344    /// $f(x, y, \mathrm{Down}) =  \operatorname{sgn}(q) |y| \lfloor |q| \rfloor.$
345    ///
346    /// $f(x, y, \mathrm{Up}) = \operatorname{sgn}(q) |y| \lceil |q| \rceil.$
347    ///
348    /// $f(x, y, \mathrm{Floor}) = |y| \lfloor q \rfloor.$
349    ///
350    /// $f(x, y, \mathrm{Ceiling}) = |y| \lceil q \rceil.$
351    ///
352    /// $$
353    /// f(x, y, \mathrm{Nearest}) = \begin{cases}
354    ///     y \lfloor q \rfloor & \text{if} \\quad
355    ///         q - \lfloor q \rfloor < \frac{1}{2} \\\\
356    ///     y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\
357    ///     y \lfloor q \rfloor &
358    ///     \text{if} \\quad q - \lfloor q \rfloor =
359    ///         \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor
360    ///     \\ \text{is even} \\\\
361    ///     y \lceil q \rceil &
362    ///     \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2}
363    ///         \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.}
364    /// \end{cases}
365    /// $$
366    ///
367    /// $f(x, y, \mathrm{Exact}) = q$, but panics if $q \notin \Z$.
368    ///
369    /// The following two expressions are equivalent:
370    /// - `x.round_to_multiple(other, Exact)`
371    /// - `{ assert!(x.divisible_by(other)); x }`
372    ///
373    /// but the latter should be used as it is clearer and more efficient.
374    ///
375    /// # Worst-case complexity
376    /// $T(n) = O(n \log n \log\log n)$
377    ///
378    /// $M(n) = O(n \log n)$
379    ///
380    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
381    ///
382    /// # Panics
383    /// - If `rm` is `Exact`, but `self` is not a multiple of `other`.
384    /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero.
385    ///
386    /// # Examples
387    /// ```
388    /// use malachite_base::num::arithmetic::traits::RoundToMultiple;
389    /// use malachite_base::num::basic::traits::Zero;
390    /// use malachite_base::rounding_modes::RoundingMode::*;
391    /// use malachite_base::strings::ToDebugString;
392    /// use malachite_nz::integer::Integer;
393    ///
394    /// assert_eq!(
395    ///     (&Integer::from(-5))
396    ///         .round_to_multiple(Integer::ZERO, Down)
397    ///         .to_debug_string(),
398    ///     "(0, Greater)"
399    /// );
400    ///
401    /// assert_eq!(
402    ///     (&Integer::from(-10))
403    ///         .round_to_multiple(Integer::from(4), Down)
404    ///         .to_debug_string(),
405    ///     "(-8, Greater)"
406    /// );
407    /// assert_eq!(
408    ///     (&Integer::from(-10))
409    ///         .round_to_multiple(Integer::from(4), Up)
410    ///         .to_debug_string(),
411    ///     "(-12, Less)"
412    /// );
413    /// assert_eq!(
414    ///     (&Integer::from(-10))
415    ///         .round_to_multiple(Integer::from(5), Exact)
416    ///         .to_debug_string(),
417    ///     "(-10, Equal)"
418    /// );
419    /// assert_eq!(
420    ///     (&Integer::from(-10))
421    ///         .round_to_multiple(Integer::from(3), Nearest)
422    ///         .to_debug_string(),
423    ///     "(-9, Greater)"
424    /// );
425    /// assert_eq!(
426    ///     (&Integer::from(-20))
427    ///         .round_to_multiple(Integer::from(3), Nearest)
428    ///         .to_debug_string(),
429    ///     "(-21, Less)"
430    /// );
431    /// assert_eq!(
432    ///     (&Integer::from(-10))
433    ///         .round_to_multiple(Integer::from(4), Nearest)
434    ///         .to_debug_string(),
435    ///     "(-8, Greater)"
436    /// );
437    /// assert_eq!(
438    ///     (&Integer::from(-14))
439    ///         .round_to_multiple(Integer::from(4), Nearest)
440    ///         .to_debug_string(),
441    ///     "(-16, Less)"
442    /// );
443    ///
444    /// assert_eq!(
445    ///     (&Integer::from(-10))
446    ///         .round_to_multiple(Integer::from(-4), Down)
447    ///         .to_debug_string(),
448    ///     "(-8, Greater)"
449    /// );
450    /// assert_eq!(
451    ///     (&Integer::from(-10))
452    ///         .round_to_multiple(Integer::from(-4), Up)
453    ///         .to_debug_string(),
454    ///     "(-12, Less)"
455    /// );
456    /// assert_eq!(
457    ///     (&Integer::from(-10))
458    ///         .round_to_multiple(Integer::from(-5), Exact)
459    ///         .to_debug_string(),
460    ///     "(-10, Equal)"
461    /// );
462    /// assert_eq!(
463    ///     (&Integer::from(-10))
464    ///         .round_to_multiple(Integer::from(-3), Nearest)
465    ///         .to_debug_string(),
466    ///     "(-9, Greater)"
467    /// );
468    /// assert_eq!(
469    ///     (&Integer::from(-20))
470    ///         .round_to_multiple(Integer::from(-3), Nearest)
471    ///         .to_debug_string(),
472    ///     "(-21, Less)"
473    /// );
474    /// assert_eq!(
475    ///     (&Integer::from(-10))
476    ///         .round_to_multiple(Integer::from(-4), Nearest)
477    ///         .to_debug_string(),
478    ///     "(-8, Greater)"
479    /// );
480    /// assert_eq!(
481    ///     (&Integer::from(-14))
482    ///         .round_to_multiple(Integer::from(-4), Nearest)
483    ///         .to_debug_string(),
484    ///     "(-16, Less)"
485    /// );
486    /// ```
487    fn round_to_multiple(self, other: Integer, rm: RoundingMode) -> (Integer, Ordering) {
488        let (n, o) = (&self.abs).round_to_multiple(other.abs, if self.sign { rm } else { -rm });
489        (
490            Integer::from_sign_and_abs(self.sign, n),
491            if self.sign { o } else { o.reverse() },
492        )
493    }
494}
495
496impl RoundToMultiple<&Integer> for &Integer {
497    type Output = Integer;
498
499    /// Rounds an [`Integer`] to a multiple of another [`Integer`], according to a specified
500    /// rounding mode. Both [`Integer`]s are taken by reference. An [`Ordering`] is also returned,
501    /// indicating whether the returned value is less than, equal to, or greater than the original
502    /// value.
503    ///
504    /// Let $q = \frac{x}{|y|}$:
505    ///
506    /// $f(x, y, \mathrm{Down}) =  \operatorname{sgn}(q) |y| \lfloor |q| \rfloor.$
507    ///
508    /// $f(x, y, \mathrm{Up}) = \operatorname{sgn}(q) |y| \lceil |q| \rceil.$
509    ///
510    /// $f(x, y, \mathrm{Floor}) = |y| \lfloor q \rfloor.$
511    ///
512    /// $f(x, y, \mathrm{Ceiling}) = |y| \lceil q \rceil.$
513    ///
514    /// $$
515    /// f(x, y, \mathrm{Nearest}) = \begin{cases}
516    ///     y \lfloor q \rfloor & \text{if} \\quad
517    ///         q - \lfloor q \rfloor < \frac{1}{2} \\\\
518    ///     y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\
519    ///     y \lfloor q \rfloor &
520    ///     \text{if} \\quad q - \lfloor q \rfloor =
521    ///         \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor
522    ///     \\ \text{is even} \\\\
523    ///     y \lceil q \rceil &
524    ///     \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2}
525    ///         \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.}
526    /// \end{cases}
527    /// $$
528    ///
529    /// $f(x, y, \mathrm{Exact}) = q$, but panics if $q \notin \Z$.
530    ///
531    /// The following two expressions are equivalent:
532    /// - `x.round_to_multiple(other, Exact)`
533    /// - `{ assert!(x.divisible_by(other)); x }`
534    ///
535    /// but the latter should be used as it is clearer and more efficient.
536    ///
537    /// # Worst-case complexity
538    /// $T(n) = O(n \log n \log\log n)$
539    ///
540    /// $M(n) = O(n \log n)$
541    ///
542    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
543    ///
544    /// # Panics
545    /// - If `rm` is `Exact`, but `self` is not a multiple of `other`.
546    /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero.
547    ///
548    /// # Examples
549    /// ```
550    /// use malachite_base::num::arithmetic::traits::RoundToMultiple;
551    /// use malachite_base::num::basic::traits::Zero;
552    /// use malachite_base::rounding_modes::RoundingMode::*;
553    /// use malachite_base::strings::ToDebugString;
554    /// use malachite_nz::integer::Integer;
555    ///
556    /// assert_eq!(
557    ///     (&Integer::from(-5))
558    ///         .round_to_multiple(&Integer::ZERO, Down)
559    ///         .to_debug_string(),
560    ///     "(0, Greater)"
561    /// );
562    ///
563    /// assert_eq!(
564    ///     (&Integer::from(-10))
565    ///         .round_to_multiple(&Integer::from(4), Down)
566    ///         .to_debug_string(),
567    ///     "(-8, Greater)"
568    /// );
569    /// assert_eq!(
570    ///     (&Integer::from(-10))
571    ///         .round_to_multiple(&Integer::from(4), Up)
572    ///         .to_debug_string(),
573    ///     "(-12, Less)"
574    /// );
575    /// assert_eq!(
576    ///     (&Integer::from(-10))
577    ///         .round_to_multiple(&Integer::from(5), Exact)
578    ///         .to_debug_string(),
579    ///     "(-10, Equal)"
580    /// );
581    /// assert_eq!(
582    ///     (&Integer::from(-10))
583    ///         .round_to_multiple(&Integer::from(3), Nearest)
584    ///         .to_debug_string(),
585    ///     "(-9, Greater)"
586    /// );
587    /// assert_eq!(
588    ///     (&Integer::from(-20))
589    ///         .round_to_multiple(&Integer::from(3), Nearest)
590    ///         .to_debug_string(),
591    ///     "(-21, Less)"
592    /// );
593    /// assert_eq!(
594    ///     (&Integer::from(-10))
595    ///         .round_to_multiple(&Integer::from(4), Nearest)
596    ///         .to_debug_string(),
597    ///     "(-8, Greater)"
598    /// );
599    /// assert_eq!(
600    ///     (&Integer::from(-14))
601    ///         .round_to_multiple(&Integer::from(4), Nearest)
602    ///         .to_debug_string(),
603    ///     "(-16, Less)"
604    /// );
605    ///
606    /// assert_eq!(
607    ///     (&Integer::from(-10))
608    ///         .round_to_multiple(&Integer::from(-4), Down)
609    ///         .to_debug_string(),
610    ///     "(-8, Greater)"
611    /// );
612    /// assert_eq!(
613    ///     (&Integer::from(-10))
614    ///         .round_to_multiple(&Integer::from(-4), Up)
615    ///         .to_debug_string(),
616    ///     "(-12, Less)"
617    /// );
618    /// assert_eq!(
619    ///     (&Integer::from(-10))
620    ///         .round_to_multiple(&Integer::from(-5), Exact)
621    ///         .to_debug_string(),
622    ///     "(-10, Equal)"
623    /// );
624    /// assert_eq!(
625    ///     (&Integer::from(-10))
626    ///         .round_to_multiple(&Integer::from(-3), Nearest)
627    ///         .to_debug_string(),
628    ///     "(-9, Greater)"
629    /// );
630    /// assert_eq!(
631    ///     (&Integer::from(-20))
632    ///         .round_to_multiple(&Integer::from(-3), Nearest)
633    ///         .to_debug_string(),
634    ///     "(-21, Less)"
635    /// );
636    /// assert_eq!(
637    ///     (&Integer::from(-10))
638    ///         .round_to_multiple(&Integer::from(-4), Nearest)
639    ///         .to_debug_string(),
640    ///     "(-8, Greater)"
641    /// );
642    /// assert_eq!(
643    ///     (&Integer::from(-14))
644    ///         .round_to_multiple(&Integer::from(-4), Nearest)
645    ///         .to_debug_string(),
646    ///     "(-16, Less)"
647    /// );
648    /// ```
649    fn round_to_multiple(self, other: &Integer, rm: RoundingMode) -> (Integer, Ordering) {
650        let (n, o) = (&self.abs).round_to_multiple(&other.abs, if self.sign { rm } else { -rm });
651        (
652            Integer::from_sign_and_abs(self.sign, n),
653            if self.sign { o } else { o.reverse() },
654        )
655    }
656}
657
658impl RoundToMultipleAssign<Self> for Integer {
659    /// Rounds an [`Integer`] to a multiple of another [`Integer`] in place, according to a
660    /// specified rounding mode. The [`Integer`] on the right-hand side is taken by value. An
661    /// [`Ordering`] is returned, indicating whether the returned value is less than, equal to, or
662    /// greater than the original value.
663    ///
664    /// See the [`RoundToMultiple`] documentation for details.
665    ///
666    /// The following two expressions are equivalent:
667    /// - `x.round_to_multiple_assign(other, Exact);`
668    /// - `assert!(x.divisible_by(other));`
669    ///
670    /// but the latter should be used as it is clearer and more efficient.
671    ///
672    /// # Worst-case complexity
673    /// $T(n) = O(n \log n \log\log n)$
674    ///
675    /// $M(n) = O(n \log n)$
676    ///
677    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
678    ///
679    /// # Panics
680    /// - If `rm` is `Exact`, but `self` is not a multiple of `other`.
681    /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero.
682    ///
683    /// # Examples
684    /// ```
685    /// use core::cmp::Ordering::*;
686    /// use malachite_base::num::arithmetic::traits::RoundToMultipleAssign;
687    /// use malachite_base::num::basic::traits::Zero;
688    /// use malachite_base::rounding_modes::RoundingMode::*;
689    /// use malachite_nz::integer::Integer;
690    ///
691    /// let mut x = Integer::from(-5);
692    /// assert_eq!(x.round_to_multiple_assign(Integer::ZERO, Down), Greater);
693    /// assert_eq!(x, 0);
694    ///
695    /// let mut x = Integer::from(-10);
696    /// assert_eq!(x.round_to_multiple_assign(Integer::from(4), Down), Greater);
697    /// assert_eq!(x, -8);
698    ///
699    /// let mut x = Integer::from(-10);
700    /// assert_eq!(x.round_to_multiple_assign(Integer::from(4), Up), Less);
701    /// assert_eq!(x, -12);
702    ///
703    /// let mut x = Integer::from(-10);
704    /// assert_eq!(x.round_to_multiple_assign(Integer::from(5), Exact), Equal);
705    /// assert_eq!(x, -10);
706    ///
707    /// let mut x = Integer::from(-10);
708    /// assert_eq!(
709    ///     x.round_to_multiple_assign(Integer::from(3), Nearest),
710    ///     Greater
711    /// );
712    /// assert_eq!(x, -9);
713    ///
714    /// let mut x = Integer::from(-20);
715    /// assert_eq!(x.round_to_multiple_assign(Integer::from(3), Nearest), Less);
716    /// assert_eq!(x, -21);
717    ///
718    /// let mut x = Integer::from(-10);
719    /// assert_eq!(
720    ///     x.round_to_multiple_assign(Integer::from(4), Nearest),
721    ///     Greater
722    /// );
723    /// assert_eq!(x, -8);
724    ///
725    /// let mut x = Integer::from(-14);
726    /// assert_eq!(x.round_to_multiple_assign(Integer::from(4), Nearest), Less);
727    /// assert_eq!(x, -16);
728    ///
729    /// let mut x = Integer::from(-10);
730    /// assert_eq!(x.round_to_multiple_assign(Integer::from(-4), Down), Greater);
731    /// assert_eq!(x, -8);
732    ///
733    /// let mut x = Integer::from(-10);
734    /// assert_eq!(x.round_to_multiple_assign(Integer::from(-4), Up), Less);
735    /// assert_eq!(x, -12);
736    ///
737    /// let mut x = Integer::from(-10);
738    /// assert_eq!(x.round_to_multiple_assign(Integer::from(-5), Exact), Equal);
739    /// assert_eq!(x, -10);
740    ///
741    /// let mut x = Integer::from(-10);
742    /// assert_eq!(
743    ///     x.round_to_multiple_assign(Integer::from(-3), Nearest),
744    ///     Greater
745    /// );
746    /// assert_eq!(x, -9);
747    ///
748    /// let mut x = Integer::from(-20);
749    /// assert_eq!(x.round_to_multiple_assign(Integer::from(-3), Nearest), Less);
750    /// assert_eq!(x, -21);
751    ///
752    /// let mut x = Integer::from(-10);
753    /// assert_eq!(
754    ///     x.round_to_multiple_assign(Integer::from(-4), Nearest),
755    ///     Greater
756    /// );
757    /// assert_eq!(x, -8);
758    ///
759    /// let mut x = Integer::from(-14);
760    /// assert_eq!(x.round_to_multiple_assign(Integer::from(-4), Nearest), Less);
761    /// assert_eq!(x, -16);
762    /// ```
763    fn round_to_multiple_assign(&mut self, other: Self, rm: RoundingMode) -> Ordering {
764        if self.sign {
765            self.abs.round_to_multiple_assign(other.abs, rm)
766        } else {
767            let o = self.abs.round_to_multiple_assign(other.abs, -rm);
768            self.sign = self.abs == 0;
769            o.reverse()
770        }
771    }
772}
773
774impl RoundToMultipleAssign<&Self> for Integer {
775    /// Rounds an [`Integer`] to a multiple of another [`Integer`] in place, according to a
776    /// specified rounding mode. The [`Integer`] on the right-hand side is taken by reference. An
777    /// [`Ordering`] is returned, indicating whether the returned value is less than, equal to, or
778    /// greater than the original value.
779    ///
780    /// See the [`RoundToMultiple`] documentation for details.
781    ///
782    /// The following two expressions are equivalent:
783    /// - `x.round_to_multiple_assign(other, Exact);`
784    /// - `assert!(x.divisible_by(other));`
785    ///
786    /// but the latter should be used as it is clearer and more efficient.
787    ///
788    /// # Worst-case complexity
789    /// $T(n) = O(n \log n \log\log n)$
790    ///
791    /// $M(n) = O(n \log n)$
792    ///
793    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
794    ///
795    /// # Panics
796    /// - If `rm` is `Exact`, but `self` is not a multiple of `other`.
797    /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero.
798    ///
799    /// # Examples
800    /// ```
801    /// use core::cmp::Ordering::*;
802    /// use malachite_base::num::arithmetic::traits::RoundToMultipleAssign;
803    /// use malachite_base::num::basic::traits::Zero;
804    /// use malachite_base::rounding_modes::RoundingMode::*;
805    /// use malachite_nz::integer::Integer;
806    ///
807    /// let mut x = Integer::from(-5);
808    /// assert_eq!(x.round_to_multiple_assign(&Integer::ZERO, Down), Greater);
809    /// assert_eq!(x, 0);
810    ///
811    /// let mut x = Integer::from(-10);
812    /// assert_eq!(x.round_to_multiple_assign(&Integer::from(4), Down), Greater);
813    /// assert_eq!(x, -8);
814    ///
815    /// let mut x = Integer::from(-10);
816    /// assert_eq!(x.round_to_multiple_assign(&Integer::from(4), Up), Less);
817    /// assert_eq!(x, -12);
818    ///
819    /// let mut x = Integer::from(-10);
820    /// assert_eq!(x.round_to_multiple_assign(&Integer::from(5), Exact), Equal);
821    /// assert_eq!(x, -10);
822    ///
823    /// let mut x = Integer::from(-10);
824    /// assert_eq!(
825    ///     x.round_to_multiple_assign(&Integer::from(3), Nearest),
826    ///     Greater
827    /// );
828    /// assert_eq!(x, -9);
829    ///
830    /// let mut x = Integer::from(-20);
831    /// assert_eq!(x.round_to_multiple_assign(&Integer::from(3), Nearest), Less);
832    /// assert_eq!(x, -21);
833    ///
834    /// let mut x = Integer::from(-10);
835    /// assert_eq!(
836    ///     x.round_to_multiple_assign(&Integer::from(4), Nearest),
837    ///     Greater
838    /// );
839    /// assert_eq!(x, -8);
840    ///
841    /// let mut x = Integer::from(-14);
842    /// assert_eq!(x.round_to_multiple_assign(&Integer::from(4), Nearest), Less);
843    /// assert_eq!(x, -16);
844    ///
845    /// let mut x = Integer::from(-10);
846    /// assert_eq!(
847    ///     x.round_to_multiple_assign(&Integer::from(-4), Down),
848    ///     Greater
849    /// );
850    /// assert_eq!(x, -8);
851    ///
852    /// let mut x = Integer::from(-10);
853    /// assert_eq!(x.round_to_multiple_assign(&Integer::from(-4), Up), Less);
854    /// assert_eq!(x, -12);
855    ///
856    /// let mut x = Integer::from(-10);
857    /// assert_eq!(x.round_to_multiple_assign(&Integer::from(-5), Exact), Equal);
858    /// assert_eq!(x, -10);
859    ///
860    /// let mut x = Integer::from(-10);
861    /// assert_eq!(
862    ///     x.round_to_multiple_assign(&Integer::from(-3), Nearest),
863    ///     Greater
864    /// );
865    /// assert_eq!(x, -9);
866    ///
867    /// let mut x = Integer::from(-20);
868    /// assert_eq!(
869    ///     x.round_to_multiple_assign(&Integer::from(-3), Nearest),
870    ///     Less
871    /// );
872    /// assert_eq!(x, -21);
873    ///
874    /// let mut x = Integer::from(-10);
875    /// assert_eq!(
876    ///     x.round_to_multiple_assign(&Integer::from(-4), Nearest),
877    ///     Greater
878    /// );
879    /// assert_eq!(x, -8);
880    ///
881    /// let mut x = Integer::from(-14);
882    /// assert_eq!(
883    ///     x.round_to_multiple_assign(&Integer::from(-4), Nearest),
884    ///     Less
885    /// );
886    /// assert_eq!(x, -16);
887    /// ```
888    fn round_to_multiple_assign(&mut self, other: &Self, rm: RoundingMode) -> Ordering {
889        if self.sign {
890            self.abs.round_to_multiple_assign(&other.abs, rm)
891        } else {
892            let o = self.abs.round_to_multiple_assign(&other.abs, -rm);
893            self.sign = self.abs == 0;
894            o.reverse()
895        }
896    }
897}