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}