malachite_float/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::Float;
10use crate::InnerFloat::Finite;
11use core::cmp::Ordering::{self, *};
12use malachite_base::num::arithmetic::traits::{IsPowerOf2, ShrRound, ShrRoundAssign};
13use malachite_base::num::basic::integers::PrimitiveInt;
14use malachite_base::num::basic::traits::{Infinity, NegativeInfinity, NegativeZero, Zero};
15use malachite_base::num::conversion::traits::SaturatingInto;
16use malachite_base::num::logic::traits::SignificantBits;
17use malachite_base::rounding_modes::RoundingMode::{self, *};
18
19impl Float {
20 pub(crate) fn shr_prec_round_assign_helper<T: PrimitiveInt>(
21 &mut self,
22 bits: T,
23 prec: u64,
24 rm: RoundingMode,
25 previous_o: Ordering,
26 ) -> Ordering {
27 if let Self(Finite {
28 significand,
29 exponent,
30 sign,
31 precision,
32 }) = self
33 {
34 let mut possibly_just_under_min = false;
35 if let Ok(bits) = bits.try_into()
36 && let Some(new_exponent) = exponent.checked_sub(bits)
37 {
38 possibly_just_under_min = true;
39 if (Self::MIN_EXPONENT..=Self::MAX_EXPONENT).contains(&new_exponent) {
40 *exponent = new_exponent;
41 return previous_o;
42 }
43 }
44 assert!(rm != Exact, "Inexact Float right-shift");
45 if bits < T::ZERO {
46 match (*sign, rm) {
47 (true, Up | Ceiling | Nearest) => {
48 *self = Self::INFINITY;
49 Greater
50 }
51 (true, Floor | Down) => {
52 *self = Self::max_finite_value_with_prec(prec);
53 Less
54 }
55 (false, Up | Floor | Nearest) => {
56 *self = Self::NEGATIVE_INFINITY;
57 Less
58 }
59 (false, Ceiling | Down) => {
60 *self = -Self::max_finite_value_with_prec(prec);
61 Greater
62 }
63 (_, Exact) => unreachable!(),
64 }
65 } else if rm == Nearest
66 && possibly_just_under_min
67 && *exponent - <T as SaturatingInto<i32>>::saturating_into(bits)
68 == Self::MIN_EXPONENT - 1
69 && (previous_o == if *sign { Less } else { Greater }
70 || !significand.is_power_of_2())
71 {
72 if *sign {
73 *self = Self::min_positive_value_prec(*precision);
74 Greater
75 } else {
76 *self = -Self::min_positive_value_prec(*precision);
77 Less
78 }
79 } else {
80 match (*sign, rm) {
81 (true, Up | Ceiling) => {
82 *self = Self::min_positive_value_prec(prec);
83 Greater
84 }
85 (true, Floor | Down | Nearest) => {
86 *self = Self::ZERO;
87 Less
88 }
89 (false, Up | Floor) => {
90 *self = -Self::min_positive_value_prec(prec);
91 Less
92 }
93 (false, Ceiling | Down | Nearest) => {
94 *self = Self::NEGATIVE_ZERO;
95 Greater
96 }
97 (_, Exact) => unreachable!(),
98 }
99 }
100 } else {
101 Equal
102 }
103 }
104
105 /// Right-shifts a [`Float`] (divides it by a power of 2), rounding the result with the
106 /// specified rounding mode and precision, and taking the [`Float`] by value.
107 ///
108 /// `NaN`, infinities, and zeros are unchanged. If the output has a precision, it is `prec`.
109 ///
110 /// $$
111 /// f(x,k,p,m) = x/2^k.
112 /// $$
113 ///
114 /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
115 /// returned instead.
116 /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$
117 /// is returned instead, where `p` is the precision of the input.
118 /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is
119 /// returned instead.
120 /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`,
121 /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is `prec`.
122 /// - If $0<f(x,k,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
123 /// - If $0<f(x,k,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
124 /// instead.
125 /// - If $0<f(x,k,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
126 /// - If $2^{-2^{30}-1}<f(x,k,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
127 /// instead.
128 /// - If $-2^{-2^{30}}<f(x,k,p,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
129 /// instead.
130 /// - If $-2^{-2^{30}}<f(x,k,p,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
131 /// instead.
132 /// - If $-2^{-2^{30}-1}\leq f(x,k,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
133 /// - If $-2^{-2^{30}}<f(x,k,p,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
134 /// returned instead.
135 ///
136 /// If you know you'll be using `Nearest`, consider using [`Float::shr_prec`] instead. If you
137 /// know that your target precision is the precision of the input, consider using
138 /// [`Float::shr_round`] instead. If both of these things are true, or you don't care about
139 /// overflow or underflow behavior, consider using `>>` instead.
140 ///
141 /// # Worst-case complexity
142 /// $T(n) = O(n)$
143 ///
144 /// $M(n) = O(n)$
145 ///
146 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
147 ///
148 /// # Panics
149 /// Panics if `rm` is `Exact` and the result overflows or underflows, or cannot be expressed
150 /// exactly with the specified precision.
151 ///
152 /// # Examples
153 /// See [here](super::shr_prec_round#shr_prec_round).
154 pub fn shr_prec_round<T: PrimitiveInt>(
155 mut self,
156 bits: T,
157 prec: u64,
158 rm: RoundingMode,
159 ) -> (Self, Ordering) {
160 let o = self.shr_prec_round_assign(bits, prec, rm);
161 (self, o)
162 }
163
164 /// Right-shifts a [`Float`] (divides it by a power of 2), rounding the result with the
165 /// specified rounding mode and precision, and taking the [`Float`] by reference.
166 ///
167 /// `NaN`, infinities, and zeros are unchanged. If the output has a precision, it is `prec`.
168 ///
169 /// $$
170 /// f(x,k,p,m) = x/2^k.
171 /// $$
172 ///
173 /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
174 /// returned instead.
175 /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$
176 /// is returned instead, where `p` is the precision of the input.
177 /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is
178 /// returned instead.
179 /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`,
180 /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is `prec`.
181 /// - If $0<f(x,k,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
182 /// - If $0<f(x,k,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
183 /// instead.
184 /// - If $0<f(x,k,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
185 /// - If $2^{-2^{30}-1}<f(x,k,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
186 /// instead.
187 /// - If $-2^{-2^{30}}<f(x,k,p,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
188 /// instead.
189 /// - If $-2^{-2^{30}}<f(x,k,p,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
190 /// instead.
191 /// - If $-2^{-2^{30}-1}\leq f(x,k,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
192 /// - If $-2^{-2^{30}}<f(x,k,p,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
193 /// returned instead.
194 ///
195 /// If you know you'll be using `Nearest`, consider using [`Float::shr_prec_ref`] instead. If
196 /// you know that your target precision is the precision of the input, consider using
197 /// [`Float::shr_round_ref`] instead. If both of these things are true, or you don't care about
198 /// overflow or underflow behavior, consider using `>>` instead.
199 ///
200 /// # Worst-case complexity
201 /// $T(n) = O(n)$
202 ///
203 /// $M(n) = O(n)$
204 ///
205 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
206 ///
207 /// # Panics
208 /// Panics if `rm` is `Exact` and the result overflows or underflows, or cannot be expressed
209 /// exactly with the specified precision.
210 ///
211 /// # Examples
212 /// See [here](super::shr_prec_round#shr_prec_round).
213 pub fn shr_prec_round_ref<T: PrimitiveInt>(
214 &self,
215 bits: T,
216 prec: u64,
217 rm: RoundingMode,
218 ) -> (Self, Ordering) {
219 let mut x = self.clone();
220 let o = x.shr_prec_round_assign(bits, prec, rm);
221 (x, o)
222 }
223
224 /// Right-shifts a [`Float`] (divides it by a power of 2) in place, rounding the result with the
225 /// specified rounding mode and precision.
226 ///
227 /// `NaN`, infinities, and zeros are unchanged. If the output has a precision, it is `prec`.
228 ///
229 /// $$
230 /// x \gets x/2^k.
231 /// $$
232 ///
233 /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
234 /// returned instead.
235 /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$
236 /// is returned instead, where `p` is the precision of the input.
237 /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is
238 /// returned instead.
239 /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`,
240 /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is `prec`.
241 /// - If $0<f(x,k,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
242 /// - If $0<f(x,k,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
243 /// instead.
244 /// - If $0<f(x,k,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
245 /// - If $2^{-2^{30}-1}<f(x,k,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
246 /// instead.
247 /// - If $-2^{-2^{30}}<f(x,k,p,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
248 /// instead.
249 /// - If $-2^{-2^{30}}<f(x,k,p,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
250 /// instead.
251 /// - If $-2^{-2^{30}-1}\leq f(x,k,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
252 /// - If $-2^{-2^{30}}<f(x,k,p,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
253 /// returned instead.
254 ///
255 /// If you know you'll be using `Nearest`, consider using [`Float::shr_prec_assign`] instead. If
256 /// you know that your target precision is the precision of the input, consider using
257 /// [`Float::shr_round_assign`] instead. If both of these things are true, or you don't care
258 /// about overflow or underflow behavior, consider using `>>=` instead.
259 ///
260 /// # Worst-case complexity
261 /// $T(n) = O(n)$
262 ///
263 /// $M(n) = O(n)$
264 ///
265 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
266 ///
267 /// # Panics
268 /// Panics if `rm` is `Exact` and the result overflows or underflows, or cannot be expressed
269 /// exactly with the specified precision.
270 ///
271 /// # Examples
272 /// See [here](super::shr_prec_round#shr_prec_round).
273 pub fn shr_prec_round_assign<T: PrimitiveInt>(
274 &mut self,
275 bits: T,
276 prec: u64,
277 rm: RoundingMode,
278 ) -> Ordering {
279 if let Self(Finite { exponent, .. }) = self {
280 let old_exponent = *exponent;
281 *exponent = 0;
282 let o = self.set_prec_round(prec, rm);
283 self.shr_prec_round_assign_helper(
284 <T as SaturatingInto<i32>>::saturating_into(bits).saturating_sub(old_exponent),
285 prec,
286 rm,
287 o,
288 )
289 } else {
290 Equal
291 }
292 }
293
294 /// Right-shifts a [`Float`] (divides it by a power of 2), rounding the result with the
295 /// specified precision, and taking the [`Float`] by value.
296 ///
297 /// `NaN`, infinities, and zeros are unchanged. If the output has a precision, it is `prec`.
298 ///
299 /// $$
300 /// f(x,k,p) = x/2^k.
301 /// $$
302 ///
303 /// - If $f(x,k,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead.
304 /// - If $f(x,k,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead.
305 /// - If $0<f(x,k,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
306 /// - If $2^{-2^{30}-1}<f(x,k,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
307 /// - If $-2^{-2^{30}-1}\leq f(x,k,p)<0$, $-0.0$ is returned instead.
308 /// - If $-2^{-2^{30}}<f(x,k,p)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
309 ///
310 /// If you know that your target precision is the precision of the input, or you don't care
311 /// about overflow or underflow behavior, consider using `>>` instead.
312 ///
313 /// # Worst-case complexity
314 /// $T(n) = O(n)$
315 ///
316 /// $M(n) = O(n)$
317 ///
318 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
319 ///
320 /// # Examples
321 /// See [here](super::shr_prec#shr_prec).
322 #[inline]
323 pub fn shr_prec<T: PrimitiveInt>(self, bits: T, prec: u64) -> (Self, Ordering) {
324 self.shr_prec_round(bits, prec, Nearest)
325 }
326
327 /// Right-shifts a [`Float`] (divides it by a power of 2), rounding the result with the
328 /// specified precision, and taking the [`Float`] by reference.
329 ///
330 /// `NaN`, infinities, and zeros are unchanged. If the output has a precision, it is `prec`.
331 ///
332 /// $$
333 /// f(x,k,p) = x/2^k.
334 /// $$
335 ///
336 /// - If $f(x,k,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead.
337 /// - If $f(x,k,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead.
338 /// - If $0<f(x,k,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
339 /// - If $2^{-2^{30}-1}<f(x,k,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
340 /// - If $-2^{-2^{30}-1}\leq f(x,k,p)<0$, $-0.0$ is returned instead.
341 /// - If $-2^{-2^{30}}<f(x,k,p)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
342 ///
343 /// If you know that your target precision is the precision of the input, or you don't care
344 /// about overflow or underflow behavior, consider using `>>` instead.
345 ///
346 /// # Worst-case complexity
347 /// $T(n) = O(n)$
348 ///
349 /// $M(n) = O(n)$
350 ///
351 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
352 ///
353 /// # Examples
354 /// See [here](super::shr_prec#shr_prec).
355 #[inline]
356 pub fn shr_prec_ref<T: PrimitiveInt>(&self, bits: T, prec: u64) -> (Self, Ordering) {
357 self.shr_prec_round_ref(bits, prec, Nearest)
358 }
359
360 /// Right-shifts a [`Float`] (divides it by a power of 2) in place, rounding the result with the
361 /// specified precision.
362 ///
363 /// `NaN`, infinities, and zeros are unchanged. If the output has a precision, it is `prec`.
364 ///
365 /// $$
366 /// x \gets x/2^k.
367 /// $$
368 ///
369 /// - If $f(x,k,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead.
370 /// - If $f(x,k,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead.
371 /// - If $0<f(x,k,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
372 /// - If $2^{-2^{30}-1}<f(x,k,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
373 /// - If $-2^{-2^{30}-1}\leq f(x,k,p)<0$, $-0.0$ is returned instead.
374 /// - If $-2^{-2^{30}}<f(x,k,p)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
375 ///
376 /// If you know that your target precision is the precision of the input, or you don't care
377 /// about overflow or underflow behavior, consider using `>>=` instead.
378 ///
379 /// # Worst-case complexity
380 /// $T(n) = O(n)$
381 ///
382 /// $M(n) = O(n)$
383 ///
384 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
385 ///
386 /// # Examples
387 /// See [here](super::shr_prec#shr_prec).
388 #[inline]
389 pub fn shr_prec_assign<T: PrimitiveInt>(&mut self, bits: T, prec: u64) -> Ordering {
390 self.shr_prec_round_assign(bits, prec, Nearest)
391 }
392}
393
394fn shr_round_primitive_int_ref<T: PrimitiveInt>(
395 x: &Float,
396 bits: T,
397 rm: RoundingMode,
398) -> (Float, Ordering) {
399 if let Float(Finite {
400 significand,
401 exponent,
402 sign,
403 precision,
404 }) = x
405 {
406 let mut possibly_just_under_min = false;
407 if let Ok(bits) = bits.try_into()
408 && let Some(new_exponent) = exponent.checked_sub(bits)
409 {
410 possibly_just_under_min = true;
411 if (Float::MIN_EXPONENT..=Float::MAX_EXPONENT).contains(&new_exponent) {
412 return (
413 Float(Finite {
414 significand: significand.clone(),
415 exponent: new_exponent,
416 sign: *sign,
417 precision: *precision,
418 }),
419 Equal,
420 );
421 }
422 }
423 assert!(rm != Exact, "Inexact Float right-shift");
424 if bits < T::ZERO {
425 match (*sign, rm) {
426 (true, Up | Ceiling | Nearest) => (Float::INFINITY, Greater),
427 (true, Floor | Down) => (Float::max_finite_value_with_prec(*precision), Less),
428 (false, Up | Floor | Nearest) => (Float::NEGATIVE_INFINITY, Less),
429 (false, Ceiling | Down) => {
430 (-Float::max_finite_value_with_prec(*precision), Greater)
431 }
432 (_, Exact) => unreachable!(),
433 }
434 } else if rm == Nearest
435 && possibly_just_under_min
436 && *exponent - <T as SaturatingInto<i32>>::saturating_into(bits)
437 == Float::MIN_EXPONENT - 1
438 && !significand.is_power_of_2()
439 {
440 if *sign {
441 (Float::min_positive_value_prec(*precision), Greater)
442 } else {
443 (-Float::min_positive_value_prec(*precision), Less)
444 }
445 } else {
446 match (*sign, rm) {
447 (true, Up | Ceiling) => (Float::min_positive_value_prec(*precision), Greater),
448 (true, Floor | Down | Nearest) => (Float::ZERO, Less),
449 (false, Up | Floor) => (-Float::min_positive_value_prec(*precision), Less),
450 (false, Ceiling | Down | Nearest) => (Float::NEGATIVE_ZERO, Greater),
451 (_, Exact) => unreachable!(),
452 }
453 }
454 } else {
455 (x.clone(), Equal)
456 }
457}
458
459fn shr_round_assign_primitive_int<T: PrimitiveInt>(
460 x: &mut Float,
461 bits: T,
462 rm: RoundingMode,
463) -> Ordering {
464 x.shr_prec_round_assign_helper(bits, x.significant_bits(), rm, Equal)
465}
466
467macro_rules! impl_natural_shr_round {
468 ($t:ident) => {
469 impl ShrRound<$t> for Float {
470 type Output = Float;
471
472 /// Right-shifts a [`Float`] (divides it by a power of 2), rounding the result with the
473 /// specified rounding mode and taking the [`Float`] by value.
474 ///
475 /// `NaN`, infinities, and zeros are unchanged. If the [`Float`] has a precision, the
476 /// output has the same precision.
477 ///
478 /// $$
479 /// f(x,k,m) = x/2^k.
480 /// $$
481 ///
482 /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$
483 /// is returned instead.
484 /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`,
485 /// $(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the
486 /// input.
487 /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$
488 /// is returned instead.
489 /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`,
490 /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the
491 /// input.
492 /// - If $0<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned
493 /// instead.
494 /// - If $0<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is
495 /// returned instead.
496 /// - If $0<f(x,k,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
497 /// - If $2^{-2^{30}-1}<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is
498 /// returned instead.
499 /// - If $-2^{-2^{30}}<f(x,k,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
500 /// instead.
501 /// - If $-2^{-2^{30}}<f(x,k,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is
502 /// returned instead.
503 /// - If $-2^{-2^{30}-1}\leq f(x,k,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned
504 /// instead.
505 /// - If $-2^{-2^{30}}<f(x,k,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
506 /// returned instead.
507 ///
508 /// If you don't care about overflow or underflow behavior, or only want the behavior of
509 /// the `Nearest` rounding mode, you can just use `>>` instead.
510 ///
511 /// # Worst-case complexity
512 /// $T(n) = O(n)$
513 ///
514 /// $M(n) = O(n)$
515 ///
516 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
517 ///
518 /// # Panics
519 /// Panics if the result overflows or underflows and `rm` is `Exact`.
520 ///
521 /// # Examples
522 /// See [here](super::shr_round#shr_round).
523 #[inline]
524 fn shr_round(mut self, bits: $t, rm: RoundingMode) -> (Float, Ordering) {
525 let o = self.shr_round_assign(bits, rm);
526 (self, o)
527 }
528 }
529
530 impl ShrRound<$t> for &Float {
531 type Output = Float;
532
533 /// Right-shifts a [`Float`] (divides it by a power of 2), rounding the result with the
534 /// specified rounding mode and taking the [`Float`] by reference.
535 ///
536 /// `NaN`, infinities, and zeros are unchanged. If the [`Float`] has a precision, the
537 /// output has the same precision.
538 ///
539 /// $$
540 /// f(x,k,m) = x/2^k.
541 /// $$
542 ///
543 /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$
544 /// is returned instead.
545 /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`,
546 /// $(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the
547 /// input.
548 /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$
549 /// is returned instead.
550 /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`,
551 /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the
552 /// input.
553 /// - If $0<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned
554 /// instead.
555 /// - If $0<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is
556 /// returned instead.
557 /// - If $0<f(x,k,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
558 /// - If $2^{-2^{30}-1}<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is
559 /// returned instead.
560 /// - If $-2^{-2^{30}}<f(x,k,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
561 /// instead.
562 /// - If $-2^{-2^{30}}<f(x,k,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is
563 /// returned instead.
564 /// - If $-2^{-2^{30}-1}\leq f(x,k,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned
565 /// instead.
566 /// - If $-2^{-2^{30}}<f(x,k,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
567 /// returned instead.
568 ///
569 /// If you don't care about overflow or underflow behavior, or only want the behavior of
570 /// the `Nearest` rounding mode, you can just use `>>` instead.
571 ///
572 /// # Worst-case complexity
573 /// $T(n) = O(n)$
574 ///
575 /// $M(n) = O(n)$
576 ///
577 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
578 ///
579 /// # Panics
580 /// Panics if the result overflows or underflows and `rm` is `Exact`.
581 ///
582 /// # Examples
583 /// See [here](super::shr_round#shr_round).
584 #[inline]
585 fn shr_round(self, bits: $t, rm: RoundingMode) -> (Float, Ordering) {
586 shr_round_primitive_int_ref(self, bits, rm)
587 }
588 }
589
590 impl ShrRoundAssign<$t> for Float {
591 /// Right-shifts a [`Float`] (divides it by a power of 2), in place, rounding the result
592 /// with the specified rounding mode.
593 ///
594 /// `NaN`, infinities, and zeros are unchanged. If the [`Float`] has a precision, the
595 /// precision is unchanged.
596 ///
597 /// $$
598 /// x\gets x/2^k.
599 /// $$
600 ///
601 /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$
602 /// is returned instead.
603 /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`,
604 /// $(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the
605 /// input.
606 /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$
607 /// is returned instead.
608 /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`,
609 /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the
610 /// input.
611 /// - If $0<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned
612 /// instead.
613 /// - If $0<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is
614 /// returned instead.
615 /// - If $0<f(x,k,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
616 /// - If $2^{-2^{30}-1}<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is
617 /// returned instead.
618 /// - If $-2^{-2^{30}}<f(x,k,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
619 /// instead.
620 /// - If $-2^{-2^{30}}<f(x,k,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is
621 /// returned instead.
622 /// - If $-2^{-2^{30}-1}\leq f(x,k,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned
623 /// instead.
624 /// - If $-2^{-2^{30}}<f(x,k,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
625 /// returned instead.
626 ///
627 /// If you don't care about overflow or underflow behavior, or only want the behavior of
628 /// the `Nearest` rounding mode, you can just use `>>=` instead.
629 ///
630 /// # Worst-case complexity
631 /// $T(n) = O(n)$
632 ///
633 /// $M(n) = O(n)$
634 ///
635 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
636 ///
637 /// # Panics
638 /// Panics if the result overflows or underflows and `rm` is `Exact`.
639 ///
640 /// # Examples
641 /// See [here](super::shr_round#shr_round_assign).
642 #[inline]
643 fn shr_round_assign(&mut self, bits: $t, rm: RoundingMode) -> Ordering {
644 shr_round_assign_primitive_int(self, bits, rm)
645 }
646 }
647 };
648}
649apply_to_primitive_ints!(impl_natural_shr_round);