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}