malachite_q/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::Rational;
10use core::cmp::Ordering::{self, *};
11use malachite_base::num::arithmetic::traits::{NegAssign, RoundToMultiple, RoundToMultipleAssign};
12use malachite_base::num::basic::traits::Zero;
13use malachite_base::num::conversion::traits::RoundingFrom;
14use malachite_base::rounding_modes::RoundingMode::{self, *};
15use malachite_nz::integer::Integer;
16
17impl RoundToMultiple<Self> for Rational {
18    type Output = Self;
19
20    /// Rounds a [`Rational`] to an integer multiple of another [`Rational`], according to a
21    /// specified rounding mode. Both [`Rational`]s are taken by value. An [`Ordering`] is also
22    /// returned, indicating whether the returned value is less than, equal to, or greater than the
23    /// original value.
24    ///
25    /// Let $q = \frac{x}{y}$:
26    ///
27    /// $f(x, y, \mathrm{Down}) = f(x, y, \mathrm{Floor}) = y \lfloor q \rfloor.$
28    ///
29    /// $f(x, y, \mathrm{Up}) = f(x, y, \mathrm{Ceiling}) = y \lceil q \rceil.$
30    ///
31    /// $$
32    /// f(x, y, \mathrm{Nearest}) = \begin{cases}
33    ///     y \lfloor q \rfloor & \text{if} \\quad
34    ///         q - \lfloor q \rfloor < \frac{1}{2} \\\\
35    ///     y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\
36    ///     y \lfloor q \rfloor &
37    ///     \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor
38    ///     \\ \text{is even} \\\\
39    ///     y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2}
40    ///         \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.}
41    /// \end{cases}
42    /// $$
43    ///
44    /// $f(x, y, \mathrm{Exact}) = x$, but panics if $q \notin \Z$.
45    ///
46    /// # Worst-case complexity
47    /// $T(n) = O(n \log n \log\log n)$
48    ///
49    /// $M(n) = O(n \log n)$
50    ///
51    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
52    ///
53    /// # Panics
54    /// - If `rm` is `Exact`, but `self` is not a multiple of `other`.
55    /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero.
56    ///
57    /// # Examples
58    /// ```
59    /// use malachite_base::num::arithmetic::traits::RoundToMultiple;
60    /// use malachite_base::num::basic::traits::Zero;
61    /// use malachite_base::num::conversion::traits::ExactFrom;
62    /// use malachite_base::rounding_modes::RoundingMode::*;
63    /// use malachite_base::strings::ToDebugString;
64    /// use malachite_q::Rational;
65    ///
66    /// assert_eq!(
67    ///     Rational::from(-5)
68    ///         .round_to_multiple(Rational::ZERO, Down)
69    ///         .to_debug_string(),
70    ///     "(0, Greater)"
71    /// );
72    ///
73    /// let q = Rational::exact_from(std::f64::consts::PI);
74    /// let hundredth = Rational::from_signeds(1, 100);
75    /// assert_eq!(
76    ///     q.clone()
77    ///         .round_to_multiple(hundredth.clone(), Down)
78    ///         .to_debug_string(),
79    ///     "(157/50, Less)"
80    /// );
81    /// assert_eq!(
82    ///     q.clone()
83    ///         .round_to_multiple(hundredth.clone(), Floor)
84    ///         .to_debug_string(),
85    ///     "(157/50, Less)"
86    /// );
87    /// assert_eq!(
88    ///     q.clone()
89    ///         .round_to_multiple(hundredth.clone(), Up)
90    ///         .to_debug_string(),
91    ///     "(63/20, Greater)"
92    /// );
93    /// assert_eq!(
94    ///     q.clone()
95    ///         .round_to_multiple(hundredth.clone(), Ceiling)
96    ///         .to_debug_string(),
97    ///     "(63/20, Greater)"
98    /// );
99    /// assert_eq!(
100    ///     q.clone()
101    ///         .round_to_multiple(hundredth.clone(), Nearest)
102    ///         .to_debug_string(),
103    ///     "(157/50, Less)"
104    /// );
105    /// ```
106    #[inline]
107    fn round_to_multiple(mut self, other: Self, rm: RoundingMode) -> (Self, Ordering) {
108        let o = self.round_to_multiple_assign(other, rm);
109        (self, o)
110    }
111}
112
113impl RoundToMultiple<&Self> for Rational {
114    type Output = Self;
115
116    /// Rounds a [`Rational`] to an integer multiple of another [`Rational`], according to a
117    /// specified rounding mode. The first [`Rational`] is taken by value and the second by
118    /// reference. An [`Ordering`] is also returned, indicating whether the returned value is less
119    /// than, equal to, or greater than the original value.
120    ///
121    /// Let $q = \frac{x}{y}$:
122    ///
123    /// $f(x, y, \mathrm{Down}) = f(x, y, \mathrm{Floor}) = y \lfloor q \rfloor.$
124    ///
125    /// $f(x, y, \mathrm{Up}) = f(x, y, \mathrm{Ceiling}) = y \lceil q \rceil.$
126    ///
127    /// $$
128    /// f(x, y, \mathrm{Nearest}) = \begin{cases}
129    ///     y \lfloor q \rfloor & \text{if} \\quad
130    ///         q - \lfloor q \rfloor < \frac{1}{2} \\\\
131    ///     y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\
132    ///     y \lfloor q \rfloor &
133    ///     \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor
134    ///     \\ \text{is even} \\\\
135    ///     y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2}
136    ///         \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.}
137    /// \end{cases}
138    /// $$
139    ///
140    /// $f(x, y, \mathrm{Exact}) = x$, but panics if $q \notin \Z$.
141    ///
142    /// # Worst-case complexity
143    /// $T(n) = O(n \log n \log\log n)$
144    ///
145    /// $M(n) = O(n \log n)$
146    ///
147    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
148    ///
149    /// # Panics
150    /// - If `rm` is `Exact`, but `self` is not a multiple of `other`.
151    /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero.
152    ///
153    /// # Examples
154    /// ```
155    /// use malachite_base::num::arithmetic::traits::RoundToMultiple;
156    /// use malachite_base::num::basic::traits::Zero;
157    /// use malachite_base::num::conversion::traits::ExactFrom;
158    /// use malachite_base::rounding_modes::RoundingMode::*;
159    /// use malachite_base::strings::ToDebugString;
160    /// use malachite_q::Rational;
161    ///
162    /// assert_eq!(
163    ///     Rational::from(-5)
164    ///         .round_to_multiple(&Rational::ZERO, Down)
165    ///         .to_debug_string(),
166    ///     "(0, Greater)"
167    /// );
168    ///
169    /// let q = Rational::exact_from(std::f64::consts::PI);
170    /// let hundredth = Rational::from_signeds(1, 100);
171    /// assert_eq!(
172    ///     q.clone()
173    ///         .round_to_multiple(&hundredth, Down)
174    ///         .to_debug_string(),
175    ///     "(157/50, Less)"
176    /// );
177    /// assert_eq!(
178    ///     q.clone()
179    ///         .round_to_multiple(&hundredth, Floor)
180    ///         .to_debug_string(),
181    ///     "(157/50, Less)"
182    /// );
183    /// assert_eq!(
184    ///     q.clone()
185    ///         .round_to_multiple(&hundredth, Up)
186    ///         .to_debug_string(),
187    ///     "(63/20, Greater)"
188    /// );
189    /// assert_eq!(
190    ///     q.clone()
191    ///         .round_to_multiple(&hundredth, Ceiling)
192    ///         .to_debug_string(),
193    ///     "(63/20, Greater)"
194    /// );
195    /// assert_eq!(
196    ///     q.clone()
197    ///         .round_to_multiple(&hundredth, Nearest)
198    ///         .to_debug_string(),
199    ///     "(157/50, Less)"
200    /// );
201    /// ```
202    #[inline]
203    fn round_to_multiple(mut self, other: &Self, rm: RoundingMode) -> (Self, Ordering) {
204        let o = self.round_to_multiple_assign(other, rm);
205        (self, o)
206    }
207}
208
209impl RoundToMultiple<Rational> for &Rational {
210    type Output = Rational;
211
212    /// Rounds a [`Rational`] to an integer multiple of another [`Rational`], according to a
213    /// specified rounding mode. The first [`Rational`] is taken by reference and the second by
214    /// value. An [`Ordering`] is also returned, indicating whether the returned value is less than,
215    /// equal to, or greater than the original value.
216    ///
217    /// Let $q = \frac{x}{y}$:
218    ///
219    /// $f(x, y, \mathrm{Down}) = f(x, y, \mathrm{Floor}) = y \lfloor q \rfloor.$
220    ///
221    /// $f(x, y, \mathrm{Up}) = f(x, y, \mathrm{Ceiling}) = y \lceil q \rceil.$
222    ///
223    /// $$
224    /// f(x, y, \mathrm{Nearest}) = \begin{cases}
225    ///     y \lfloor q \rfloor & \text{if} \\quad
226    ///         q - \lfloor q \rfloor < \frac{1}{2} \\\\
227    ///     y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\
228    ///     y \lfloor q \rfloor &
229    ///     \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor
230    ///     \\ \text{is even} \\\\
231    ///     y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2}
232    ///         \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.}
233    /// \end{cases}
234    /// $$
235    ///
236    /// $f(x, y, \mathrm{Exact}) = x$, but panics if $q \notin \Z$.
237    ///
238    /// # Worst-case complexity
239    /// $T(n) = O(n \log n \log\log n)$
240    ///
241    /// $M(n) = O(n \log n)$
242    ///
243    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
244    ///
245    /// # Panics
246    /// - If `rm` is `Exact`, but `self` is not a multiple of `other`.
247    /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero.
248    ///
249    /// # Examples
250    /// ```
251    /// use malachite_base::num::arithmetic::traits::RoundToMultiple;
252    /// use malachite_base::num::basic::traits::Zero;
253    /// use malachite_base::num::conversion::traits::ExactFrom;
254    /// use malachite_base::rounding_modes::RoundingMode::*;
255    /// use malachite_base::strings::ToDebugString;
256    /// use malachite_q::Rational;
257    ///
258    /// assert_eq!(
259    ///     (&Rational::from(-5))
260    ///         .round_to_multiple(Rational::ZERO, Down)
261    ///         .to_debug_string(),
262    ///     "(0, Greater)"
263    /// );
264    ///
265    /// let q = Rational::exact_from(std::f64::consts::PI);
266    /// let hundredth = Rational::from_signeds(1, 100);
267    /// assert_eq!(
268    ///     (&q).round_to_multiple(hundredth.clone(), Down)
269    ///         .to_debug_string(),
270    ///     "(157/50, Less)"
271    /// );
272    /// assert_eq!(
273    ///     (&q).round_to_multiple(hundredth.clone(), Floor)
274    ///         .to_debug_string(),
275    ///     "(157/50, Less)"
276    /// );
277    /// assert_eq!(
278    ///     (&q).round_to_multiple(hundredth.clone(), Up)
279    ///         .to_debug_string(),
280    ///     "(63/20, Greater)"
281    /// );
282    /// assert_eq!(
283    ///     (&q).round_to_multiple(hundredth.clone(), Ceiling)
284    ///         .to_debug_string(),
285    ///     "(63/20, Greater)"
286    /// );
287    /// assert_eq!(
288    ///     (&q).round_to_multiple(hundredth.clone(), Nearest)
289    ///         .to_debug_string(),
290    ///     "(157/50, Less)"
291    /// );
292    /// ```
293    fn round_to_multiple(self, other: Rational, mut rm: RoundingMode) -> (Rational, Ordering) {
294        if *self == other {
295            return (self.clone(), Equal);
296        }
297        if other == 0u32 {
298            if rm == Down || rm == Nearest || rm == if *self >= 0u32 { Floor } else { Ceiling } {
299                return (Rational::ZERO, if *self >= 0u32 { Less } else { Greater });
300            }
301            panic!("Cannot round {self} to zero using RoundingMode {rm}");
302        }
303        if !other.sign {
304            rm.neg_assign();
305        }
306        let (x, mut o) = Integer::rounding_from(self / &other, rm);
307        if !other.sign {
308            o = o.reverse();
309        }
310        (Rational::from(x) * other, o)
311    }
312}
313
314impl RoundToMultiple<&Rational> for &Rational {
315    type Output = Rational;
316
317    /// Rounds a [`Rational`] to an integer multiple of another [`Rational`], according to a
318    /// specified rounding mode. Both [`Rational`]s are taken by reference. An [`Ordering`] is also
319    /// returned, indicating whether the returned value is less than, equal to, or greater than the
320    /// original value.
321    ///
322    /// Let $q = \frac{x}{y}$:
323    ///
324    /// $f(x, y, \mathrm{Down}) = f(x, y, \mathrm{Floor}) = y \lfloor q \rfloor.$
325    ///
326    /// $f(x, y, \mathrm{Up}) = f(x, y, \mathrm{Ceiling}) = y \lceil q \rceil.$
327    ///
328    /// $$
329    /// f(x, y, \mathrm{Nearest}) = \begin{cases}
330    ///     y \lfloor q \rfloor & \text{if} \\quad
331    ///         q - \lfloor q \rfloor < \frac{1}{2} \\\\
332    ///     y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor > \frac{1}{2} \\\\
333    ///     y \lfloor q \rfloor &
334    ///     \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor
335    ///     \\ \text{is even} \\\\
336    ///     y \lceil q \rceil & \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2}
337    ///         \\ \text{and} \\ \lfloor q \rfloor \\ \text{is odd.}
338    /// \end{cases}
339    /// $$
340    ///
341    /// $f(x, y, \mathrm{Exact}) = x$, but panics if $q \notin \Z$.
342    ///
343    /// # Worst-case complexity
344    /// $T(n) = O(n \log n \log\log n)$
345    ///
346    /// $M(n) = O(n \log n)$
347    ///
348    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
349    ///
350    /// # Panics
351    /// - If `rm` is `Exact`, but `self` is not a multiple of `other`.
352    /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero.
353    ///
354    /// # Examples
355    /// ```
356    /// use malachite_base::num::arithmetic::traits::RoundToMultiple;
357    /// use malachite_base::num::basic::traits::Zero;
358    /// use malachite_base::num::conversion::traits::ExactFrom;
359    /// use malachite_base::rounding_modes::RoundingMode::*;
360    /// use malachite_base::strings::ToDebugString;
361    /// use malachite_q::Rational;
362    ///
363    /// assert_eq!(
364    ///     (&Rational::from(-5))
365    ///         .round_to_multiple(&Rational::ZERO, Down)
366    ///         .to_debug_string(),
367    ///     "(0, Greater)"
368    /// );
369    ///
370    /// let q = Rational::exact_from(std::f64::consts::PI);
371    /// let hundredth = Rational::from_signeds(1, 100);
372    /// assert_eq!(
373    ///     (&q).round_to_multiple(&hundredth, Down).to_debug_string(),
374    ///     "(157/50, Less)"
375    /// );
376    /// assert_eq!(
377    ///     (&q).round_to_multiple(&hundredth, Floor).to_debug_string(),
378    ///     "(157/50, Less)"
379    /// );
380    /// assert_eq!(
381    ///     (&q).round_to_multiple(&hundredth, Up).to_debug_string(),
382    ///     "(63/20, Greater)"
383    /// );
384    /// assert_eq!(
385    ///     (&q).round_to_multiple(&hundredth, Ceiling)
386    ///         .to_debug_string(),
387    ///     "(63/20, Greater)"
388    /// );
389    /// assert_eq!(
390    ///     (&q).round_to_multiple(&hundredth, Nearest)
391    ///         .to_debug_string(),
392    ///     "(157/50, Less)"
393    /// );
394    /// ```
395    fn round_to_multiple(self, other: &Rational, mut rm: RoundingMode) -> (Rational, Ordering) {
396        if self == other {
397            return (self.clone(), Equal);
398        }
399        if *other == 0u32 {
400            if rm == Down || rm == Nearest || rm == if *self >= 0u32 { Floor } else { Ceiling } {
401                return (Rational::ZERO, if *self >= 0 { Less } else { Greater });
402            }
403            panic!("Cannot round {self} to zero using RoundingMode {rm}");
404        }
405        if !other.sign {
406            rm.neg_assign();
407        }
408        let (x, mut o) = Integer::rounding_from(self / other, rm);
409        if !other.sign {
410            o = o.reverse();
411        }
412        (Rational::from(x) * other, o)
413    }
414}
415
416impl RoundToMultipleAssign<Self> for Rational {
417    /// Rounds a [`Rational`] to an integer multiple of another [`Rational`] in place, according to
418    /// a  specified rounding mode. The [`Rational`] on the right-hand side is taken by value. An
419    /// [`Ordering`] is returned, indicating whether the returned value is less than, equal to, or
420    /// greater than the original value.
421    ///
422    /// See the [`RoundToMultiple`] documentation for details.
423    ///
424    /// # Worst-case complexity
425    /// $T(n) = O(n \log n \log\log n)$
426    ///
427    /// $M(n) = O(n \log n)$
428    ///
429    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
430    ///
431    /// # Panics
432    /// - If `rm` is `Exact`, but `self` is not a multiple of `other`.
433    /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero.
434    ///
435    /// # Examples
436    /// ```
437    /// use malachite_base::num::arithmetic::traits::RoundToMultipleAssign;
438    /// use malachite_base::num::basic::traits::Zero;
439    /// use malachite_base::num::conversion::traits::ExactFrom;
440    /// use malachite_base::rounding_modes::RoundingMode::*;
441    /// use malachite_q::Rational;
442    /// use std::cmp::Ordering::*;
443    ///
444    /// let mut x = Rational::from(-5);
445    /// assert_eq!(x.round_to_multiple_assign(Rational::ZERO, Down), Greater);
446    /// assert_eq!(x, 0);
447    ///
448    /// let q = Rational::exact_from(std::f64::consts::PI);
449    /// let hundredth = Rational::from_signeds(1, 100);
450    ///
451    /// let mut x = q.clone();
452    /// assert_eq!(x.round_to_multiple_assign(hundredth.clone(), Down), Less);
453    /// assert_eq!(x.to_string(), "157/50");
454    ///
455    /// let mut x = q.clone();
456    /// assert_eq!(x.round_to_multiple_assign(hundredth.clone(), Floor), Less);
457    /// assert_eq!(x.to_string(), "157/50");
458    ///
459    /// let mut x = q.clone();
460    /// assert_eq!(x.round_to_multiple_assign(hundredth.clone(), Up), Greater);
461    /// assert_eq!(x.to_string(), "63/20");
462    ///
463    /// let mut x = q.clone();
464    /// assert_eq!(
465    ///     x.round_to_multiple_assign(hundredth.clone(), Ceiling),
466    ///     Greater
467    /// );
468    /// assert_eq!(x.to_string(), "63/20");
469    ///
470    /// let mut x = q.clone();
471    /// assert_eq!(x.round_to_multiple_assign(hundredth.clone(), Nearest), Less);
472    /// assert_eq!(x.to_string(), "157/50");
473    /// ```
474    fn round_to_multiple_assign(&mut self, other: Self, mut rm: RoundingMode) -> Ordering {
475        if *self == other {
476            return Equal;
477        }
478        if other == 0u32 {
479            if rm == Down || rm == Nearest || rm == if *self >= 0u32 { Floor } else { Ceiling } {
480                let o = if *self >= 0 { Less } else { Greater };
481                *self = Self::ZERO;
482                return o;
483            }
484            panic!("Cannot round {self} to zero using RoundingMode {rm}");
485        }
486        if !other.sign {
487            rm.neg_assign();
488        }
489        *self /= &other;
490        let (x, o) = Integer::rounding_from(&*self, rm);
491        let other_sign = other.sign;
492        *self = Self::from(x) * other;
493        if other_sign { o } else { o.reverse() }
494    }
495}
496
497impl RoundToMultipleAssign<&Self> for Rational {
498    /// Rounds a [`Rational`] to an integer multiple of another [`Rational`] in place, according to
499    /// a specified rounding mode. The [`Rational`] on the right-hand side is taken by reference. An
500    /// [`Ordering`] is returned, indicating whether the returned value is less than, equal to, or
501    /// greater than the original value.
502    ///
503    /// See the [`RoundToMultiple`] documentation for details.
504    ///
505    /// # Worst-case complexity
506    /// $T(n) = O(n \log n \log\log n)$
507    ///
508    /// $M(n) = O(n \log n)$
509    ///
510    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
511    ///
512    /// # Panics
513    /// - If `rm` is `Exact`, but `self` is not a multiple of `other`.
514    /// - If `self` is nonzero, `other` is zero, and `rm` is trying to round away from zero.
515    ///
516    /// # Examples
517    /// ```
518    /// use malachite_base::num::arithmetic::traits::RoundToMultipleAssign;
519    /// use malachite_base::num::basic::traits::Zero;
520    /// use malachite_base::num::conversion::traits::ExactFrom;
521    /// use malachite_base::rounding_modes::RoundingMode::*;
522    /// use malachite_q::Rational;
523    /// use std::cmp::Ordering::*;
524    ///
525    /// let mut x = Rational::from(-5);
526    /// assert_eq!(x.round_to_multiple_assign(&Rational::ZERO, Down), Greater);
527    /// assert_eq!(x, 0);
528    ///
529    /// let q = Rational::exact_from(std::f64::consts::PI);
530    /// let hundredth = Rational::from_signeds(1, 100);
531    ///
532    /// let mut x = q.clone();
533    /// assert_eq!(x.round_to_multiple_assign(&hundredth, Down), Less);
534    /// assert_eq!(x.to_string(), "157/50");
535    ///
536    /// let mut x = q.clone();
537    /// assert_eq!(x.round_to_multiple_assign(&hundredth, Floor), Less);
538    /// assert_eq!(x.to_string(), "157/50");
539    ///
540    /// let mut x = q.clone();
541    /// assert_eq!(x.round_to_multiple_assign(&hundredth, Up), Greater);
542    /// assert_eq!(x.to_string(), "63/20");
543    ///
544    /// let mut x = q.clone();
545    /// assert_eq!(x.round_to_multiple_assign(&hundredth, Ceiling), Greater);
546    /// assert_eq!(x.to_string(), "63/20");
547    ///
548    /// let mut x = q.clone();
549    /// assert_eq!(x.round_to_multiple_assign(&hundredth, Nearest), Less);
550    /// assert_eq!(x.to_string(), "157/50");
551    /// ```
552    fn round_to_multiple_assign(&mut self, other: &Self, mut rm: RoundingMode) -> Ordering {
553        if self == other {
554            return Equal;
555        }
556        if *other == 0u32 {
557            if rm == Down || rm == Nearest || rm == if *self >= 0u32 { Floor } else { Ceiling } {
558                let o = if *self >= 0u32 { Less } else { Greater };
559                *self = Self::ZERO;
560                return o;
561            }
562            panic!("Cannot round {self} to zero using RoundingMode {rm}");
563        }
564        if !other.sign {
565            rm.neg_assign();
566        }
567        *self /= other;
568        let (x, o) = Integer::rounding_from(&*self, rm);
569        *self = Self::from(x) * other;
570        if other.sign { o } else { o.reverse() }
571    }
572}