malachite_nz/integer/arithmetic/shr_round.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 crate::natural::Natural;
11use core::cmp::Ordering::{self, *};
12use core::ops::{Shl, ShlAssign};
13use malachite_base::num::arithmetic::traits::{ShrRound, ShrRoundAssign, UnsignedAbs};
14use malachite_base::num::basic::traits::Zero;
15use malachite_base::rounding_modes::RoundingMode;
16
17fn shr_round_unsigned_ref_i<'a, T>(x: &'a Integer, bits: T, rm: RoundingMode) -> (Integer, Ordering)
18where
19 &'a Natural: ShrRound<T, Output = Natural>,
20{
21 match *x {
22 Integer {
23 sign: true,
24 ref abs,
25 } => {
26 let (s, o) = abs.shr_round(bits, rm);
27 (Integer { sign: true, abs: s }, o)
28 }
29 Integer {
30 sign: false,
31 ref abs,
32 } => {
33 let (abs_shifted, o) = abs.shr_round(bits, -rm);
34 (
35 if abs_shifted == 0 {
36 Integer::ZERO
37 } else {
38 Integer {
39 sign: false,
40 abs: abs_shifted,
41 }
42 },
43 o.reverse(),
44 )
45 }
46 }
47}
48
49fn shr_round_assign_unsigned_i<T>(x: &mut Integer, bits: T, rm: RoundingMode) -> Ordering
50where
51 Natural: ShrRoundAssign<T>,
52{
53 match *x {
54 Integer {
55 sign: true,
56 ref mut abs,
57 } => abs.shr_round_assign(bits, rm),
58 Integer {
59 sign: false,
60 ref mut abs,
61 } => {
62 let o = abs.shr_round_assign(bits, -rm);
63 if *abs == 0 {
64 x.sign = true;
65 }
66 o.reverse()
67 }
68 }
69}
70
71macro_rules! impl_shr_round_unsigned {
72 ($t:ident) => {
73 impl ShrRound<$t> for Integer {
74 type Output = Integer;
75
76 /// Shifts an [`Integer`] right (divides it by a power of 2), taking it by value, and
77 /// rounds according to the specified rounding mode. An [`Ordering`] is also returned,
78 /// indicating whether the returned value is less than, equal to, or greater than the
79 /// exact value.
80 ///
81 /// Passing `Floor` is equivalent to using `>>`. To test whether `Exact` can be passed,
82 /// use `self.divisible_by_power_of_2(bits)`.
83 ///
84 /// Let $q = \frac{x}{2^k}$, and let $g$ be the function that just returns the first
85 /// element of the pair, without the [`Ordering`]:
86 ///
87 /// $f(x, k, \mathrm{Down}) = \operatorname{sgn}(q) \lfloor |q| \rfloor.$
88 ///
89 /// $f(x, k, \mathrm{Up}) = \operatorname{sgn}(q) \lceil |q| \rceil.$
90 ///
91 /// $f(x, k, \mathrm{Floor}) = \lfloor q \rfloor.$
92 ///
93 /// $f(x, k, \mathrm{Ceiling}) = \lceil q \rceil.$
94 ///
95 /// $$
96 /// f(x, k, \mathrm{Nearest}) = \begin{cases}
97 /// \lfloor q \rfloor & \text{if}
98 /// \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\
99 /// \lceil q \rceil & \text{if}
100 /// \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\
101 /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor =
102 /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor
103 /// \\ \text{is even}, \\\\
104 /// \lceil q \rceil &
105 /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and}
106 /// \\ \lfloor q \rfloor \\ \text{is odd}.
107 /// \end{cases}
108 /// $$
109 ///
110 /// $f(x, k, \mathrm{Exact}) = q$, but panics if $q \notin \Z$.
111 ///
112 /// Then
113 ///
114 /// $f(x, k, r) = (g(x, k, r), \operatorname{cmp}(g(x, k, r), q))$.
115 ///
116 /// # Worst-case complexity
117 /// $T(n) = O(n)$
118 ///
119 /// $M(n) = O(1)$
120 ///
121 /// where $T$ is time, $M$ is additional memory and $n$ is `self.significant_bits()`.
122 ///
123 /// # Panics
124 /// Let $k$ be `bits`. Panics if `rm` is `Exact` but `self` is not divisible by $2^k$.
125 ///
126 /// # Examples
127 /// See [here](super::shr_round#shr_round).
128 #[inline]
129 fn shr_round(mut self, bits: $t, rm: RoundingMode) -> (Integer, Ordering) {
130 let o = self.shr_round_assign(bits, rm);
131 (self, o)
132 }
133 }
134
135 impl<'a> ShrRound<$t> for &Integer {
136 type Output = Integer;
137
138 /// Shifts an [`Integer`] right (divides it by a power of 2), taking it by reference,
139 /// and rounds according to the specified rounding mode. An [`Ordering`] is also
140 /// returned, indicating whether the returned value is less than, equal to, or greater
141 /// than the exact value.
142 ///
143 /// Passing `Floor` is equivalent to using `>>`. To test whether `Exact` can be passed,
144 /// use `self.divisible_by_power_of_2(bits)`.
145 ///
146 /// Let $q = \frac{x}{2^k}$, and let $g$ be the function that just returns the first
147 /// element of the pair, without the [`Ordering`]:
148 ///
149 /// $f(x, k, \mathrm{Down}) = \operatorname{sgn}(q) \lfloor |q| \rfloor.$
150 ///
151 /// $f(x, k, \mathrm{Up}) = \operatorname{sgn}(q) \lceil |q| \rceil.$
152 ///
153 /// $f(x, k, \mathrm{Floor}) = \lfloor q \rfloor.$
154 ///
155 /// $f(x, k, \mathrm{Ceiling}) = \lceil q \rceil.$
156 ///
157 /// $$
158 /// f(x, k, \mathrm{Nearest}) = \begin{cases}
159 /// \lfloor q \rfloor & \text{if}
160 /// \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\
161 /// \lceil q \rceil & \text{if}
162 /// \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\
163 /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor =
164 /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor
165 /// \\ \text{is even}, \\\\
166 /// \lceil q \rceil &
167 /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and}
168 /// \\ \lfloor q \rfloor \\ \text{is odd}.
169 /// \end{cases}
170 /// $$
171 ///
172 /// $f(x, k, \mathrm{Exact}) = q$, but panics if $q \notin \Z$.
173 ///
174 /// Then
175 ///
176 /// $f(x, k, r) = (g(x, k, r), \operatorname{cmp}(g(x, k, r), q))$.
177 ///
178 /// # Worst-case complexity
179 /// $T(n) = O(n)$
180 ///
181 /// $M(n) = O(1)$
182 ///
183 /// where $T$ is time, $M$ is additional memory and $n$ is `self.significant_bits()`.
184 ///
185 /// # Panics
186 /// Let $k$ be `bits`. Panics if `rm` is `Exact` but `self` is not divisible by $2^k$.
187 ///
188 /// # Examples
189 /// See [here](super::shr_round#shr_round).
190 #[inline]
191 fn shr_round(self, bits: $t, rm: RoundingMode) -> (Integer, Ordering) {
192 shr_round_unsigned_ref_i(self, bits, rm)
193 }
194 }
195
196 impl ShrRoundAssign<$t> for Integer {
197 /// Shifts a [`Natural`] right (divides it by a power of 2) and rounds according to the
198 /// specified rounding mode, in place. Passing `Floor` is equivalent to using `>>=`. To
199 /// test whether `Exact` can be passed, use `self.divisible_by_power_of_2(bits)`. An
200 /// [`Ordering`] is returned, indicating whether the assigned value is less than, equal
201 /// to, or greater than the exact value.
202 ///
203 /// See the [`ShrRound`] documentation for details.
204 ///
205 /// # Worst-case complexity
206 /// $T(n) = O(n)$
207 ///
208 /// $M(n) = O(1)$
209 ///
210 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
211 ///
212 /// # Panics
213 /// Let $k$ be `bits`. Panics if `rm` is `Exact` but `self` is not divisible by $2^k$.
214 ///
215 /// # Examples
216 /// See [here](super::shr_round#shr_round_assign).
217 fn shr_round_assign(&mut self, bits: $t, rm: RoundingMode) -> Ordering {
218 shr_round_assign_unsigned_i(self, bits, rm)
219 }
220 }
221 };
222}
223apply_to_unsigneds!(impl_shr_round_unsigned);
224
225fn shr_round_signed_ref_i<'a, U, S: Copy + Ord + UnsignedAbs<Output = U> + Zero>(
226 x: &'a Integer,
227 bits: S,
228 rm: RoundingMode,
229) -> (Integer, Ordering)
230where
231 &'a Integer: Shl<U, Output = Integer> + ShrRound<U, Output = Integer>,
232{
233 if bits >= S::ZERO {
234 x.shr_round(bits.unsigned_abs(), rm)
235 } else {
236 (x << bits.unsigned_abs(), Equal)
237 }
238}
239
240fn shr_round_assign_signed_i<U, S: Copy + Ord + UnsignedAbs<Output = U> + Zero>(
241 x: &mut Integer,
242 bits: S,
243 rm: RoundingMode,
244) -> Ordering
245where
246 Integer: ShlAssign<U> + ShrRoundAssign<U>,
247{
248 if bits >= S::ZERO {
249 x.shr_round_assign(bits.unsigned_abs(), rm)
250 } else {
251 *x <<= bits.unsigned_abs();
252 Equal
253 }
254}
255
256macro_rules! impl_shr_round_signed {
257 ($t:ident) => {
258 impl ShrRound<$t> for Integer {
259 type Output = Integer;
260
261 /// Shifts an [`Integer`] right (divides or multiplies it by a power of 2), taking it by
262 /// value, and rounds according to the specified rounding mode. An [`Ordering`] is also
263 /// returned, indicating whether the returned value is less than, equal to, or greater
264 /// than the exact value. If `bits` is negative, then the returned [`Ordering`] is
265 /// always `Equal`, even if the higher bits of the result are lost.
266 ///
267 /// Passing `Floor` is equivalent to using `>>`. To test whether `Exact` can be passed,
268 /// use `self.divisible_by_power_of_2(bits)`.
269 ///
270 /// Let $q = \frac{x}{2^k}$, and let $g$ be the function that just returns the first
271 /// element of the pair, without the [`Ordering`]:
272 ///
273 /// $f(x, k, \mathrm{Down}) = \operatorname{sgn}(q) \lfloor |q| \rfloor.$
274 ///
275 /// $f(x, k, \mathrm{Up}) = \operatorname{sgn}(q) \lceil |q| \rceil.$
276 ///
277 /// $f(x, k, \mathrm{Floor}) = \lfloor q \rfloor.$
278 ///
279 /// $f(x, k, \mathrm{Ceiling}) = \lceil q \rceil.$
280 ///
281 /// $$
282 /// f(x, k, \mathrm{Nearest}) = \begin{cases}
283 /// \lfloor q \rfloor & \text{if}
284 /// \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\
285 /// \lceil q \rceil & \text{if}
286 /// \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\
287 /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor =
288 /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor
289 /// \\ \text{is even}, \\\\
290 /// \lceil q \rceil &
291 /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and}
292 /// \\ \lfloor q \rfloor \\ \text{is odd}.
293 /// \end{cases}
294 /// $$
295 ///
296 /// $f(x, k, \mathrm{Exact}) = q$, but panics if $q \notin \Z$.
297 ///
298 /// Then
299 ///
300 /// $f(x, k, r) = (g(x, k, r), \operatorname{cmp}(g(x, k, r), q))$.
301 ///
302 /// # Worst-case complexity
303 /// $T(n, m) = O(n + m)$
304 ///
305 /// $M(n, m) = O(n + m)$
306 ///
307 /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and
308 /// $m$ is `max(-bits, 0)`.
309 ///
310 /// # Panics
311 /// Let $k$ be `bits`. Panics if $k$ is positive and `rm` is `Exact` but `self` is not
312 /// divisible by $2^k$.
313 ///
314 /// # Examples
315 /// See [here](super::shr_round#shr_round).
316 #[inline]
317 fn shr_round(mut self, bits: $t, rm: RoundingMode) -> (Integer, Ordering) {
318 let o = self.shr_round_assign(bits, rm);
319 (self, o)
320 }
321 }
322
323 impl<'a> ShrRound<$t> for &Integer {
324 type Output = Integer;
325
326 /// Shifts an [`Integer`] right (divides or multiplies it by a power of 2), taking it by
327 /// reference, and rounds according to the specified rounding mode. An [`Ordering`] is
328 /// also returned, indicating whether the returned value is less than, equal to, or
329 /// greater than the exact value. If `bits` is negative, then the returned [`Ordering`]
330 /// is always `Equal`, even if the higher bits of the result are lost.
331 ///
332 /// Passing `Floor` is equivalent to using `>>`. To test whether `Exact` can be passed,
333 /// use `self.divisible_by_power_of_2(bits)`.
334 ///
335 /// Let $q = \frac{x}{2^k}$, and let $g$ be the function that just returns the first
336 /// element of the pair, without the [`Ordering`]:
337 ///
338 /// $f(x, k, \mathrm{Down}) = \operatorname{sgn}(q) \lfloor |q| \rfloor.$
339 ///
340 /// $f(x, k, \mathrm{Up}) = \operatorname{sgn}(q) \lceil |q| \rceil.$
341 ///
342 /// $f(x, k, \mathrm{Floor}) = \lfloor q \rfloor.$
343 ///
344 /// $f(x, k, \mathrm{Ceiling}) = \lceil q \rceil.$
345 ///
346 /// $$
347 /// f(x, k, \mathrm{Nearest}) = \begin{cases}
348 /// \lfloor q \rfloor & \text{if}
349 /// \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\
350 /// \lceil q \rceil & \text{if}
351 /// \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\
352 /// \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor =
353 /// \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor
354 /// \\ \text{is even}, \\\\
355 /// \lceil q \rceil &
356 /// \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and}
357 /// \\ \lfloor q \rfloor \\ \text{is odd}.
358 /// \end{cases}
359 /// $$
360 ///
361 /// $f(x, k, \mathrm{Exact}) = q$, but panics if $q \notin \Z$.
362 ///
363 /// Then
364 ///
365 /// $f(x, k, r) = (g(x, k, r), \operatorname{cmp}(g(x, k, r), q))$.
366 ///
367 /// # Worst-case complexity
368 /// $T(n, m) = O(n + m)$
369 ///
370 /// $M(n, m) = O(n + m)$
371 ///
372 /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and
373 /// $m$ is `max(-bits, 0)`.
374 ///
375 /// # Panics
376 /// Let $k$ be `bits`. Panics if $k$ is positive and `rm` is `Exact` but `self` is not
377 /// divisible by $2^k$.
378 ///
379 /// # Examples
380 /// See [here](super::shr_round#shr_round).
381 #[inline]
382 fn shr_round(self, bits: $t, rm: RoundingMode) -> (Integer, Ordering) {
383 shr_round_signed_ref_i(self, bits, rm)
384 }
385 }
386
387 impl ShrRoundAssign<$t> for Integer {
388 /// Shifts an [`Integer`] right (divides or multiplies it by a power of 2) and rounds
389 /// according to the specified rounding mode, in place. An [`Ordering`] is returned,
390 /// indicating whether the assigned value is less than, equal to, or greater than the
391 /// exact value. If `bits` is negative, then the returned [`Ordering`] is always
392 /// `Equal`, even if the higher bits of the result are lost.
393 ///
394 /// Passing `Floor` is equivalent to using `>>`. To test whether `Exact` can be passed,
395 /// use `self.divisible_by_power_of_2(bits)`.
396 ///
397 /// See the [`ShrRound`] documentation for details.
398 ///
399 /// # Worst-case complexity
400 /// $T(n, m) = O(n + m)$
401 ///
402 /// $M(n, m) = O(n + m)$
403 ///
404 /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and
405 /// $m$ is `max(-bits, 0)`.
406 ///
407 /// # Panics
408 /// Let $k$ be `bits`. Panics if $k$ is positive and `rm` is `Exact` but `self` is not
409 /// divisible by $2^k$.
410 ///
411 /// # Examples
412 /// See [here](super::shr_round#shr_round_assign).
413 #[inline]
414 fn shr_round_assign(&mut self, bits: $t, rm: RoundingMode) -> Ordering {
415 shr_round_assign_signed_i(self, bits, rm)
416 }
417 }
418 };
419}
420apply_to_signeds!(impl_shr_round_signed);