malachite_float/arithmetic/shl_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 crate::malachite_base::num::logic::traits::SignificantBits;
12use core::cmp::Ordering::{self, *};
13use malachite_base::num::arithmetic::traits::{IsPowerOf2, ShlRound, ShlRoundAssign};
14use malachite_base::num::basic::integers::PrimitiveInt;
15use malachite_base::num::basic::traits::{Infinity, NegativeInfinity, NegativeZero, Zero};
16use malachite_base::num::conversion::traits::SaturatingInto;
17use malachite_base::rounding_modes::RoundingMode::{self, *};
18
19impl Float {
20 pub(crate) fn shl_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_add(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 left-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 /// Left-shifts a [`Float`] (multiplies 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) = x2^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::shl_prec`] instead. If you
137 /// know that your target precision is the precision of the input, consider using
138 /// [`Float::shl_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::shl_prec_round#shl_prec_round).
154 pub fn shl_prec_round<T: PrimitiveInt>(
155 mut self,
156 bits: T,
157 prec: u64,
158 rm: RoundingMode,
159 ) -> (Self, Ordering) {
160 let o = self.shl_prec_round_assign(bits, prec, rm);
161 (self, o)
162 }
163
164 /// Left-shifts a [`Float`] (multiplies 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) = x2^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::shl_prec_ref`] instead. If
196 /// you know that your target precision is the precision of the input, consider using
197 /// [`Float::shl_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::shl_prec_round#shl_prec_round).
213 pub fn shl_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.shl_prec_round_assign(bits, prec, rm);
221 (x, o)
222 }
223
224 /// Left-shifts a [`Float`] (multiplies it by a power of 2) in place, rounding the result with
225 /// the 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 x2^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::shl_prec_assign`] instead. If
256 /// you know that your target precision is the precision of the input, consider using
257 /// [`Float::shl_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::shl_prec_round#shl_prec_round).
273 pub fn shl_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.shl_prec_round_assign_helper(
284 <T as SaturatingInto<i32>>::saturating_into(bits).saturating_add(old_exponent),
285 prec,
286 rm,
287 o,
288 )
289 } else {
290 Equal
291 }
292 }
293
294 /// Left-shifts a [`Float`] (multiplies 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) = x2^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::shl_prec#shl_prec).
322 #[inline]
323 pub fn shl_prec<T: PrimitiveInt>(self, bits: T, prec: u64) -> (Self, Ordering) {
324 self.shl_prec_round(bits, prec, Nearest)
325 }
326
327 /// Left-shifts a [`Float`] (multiplies 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) = x2^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::shl_prec#shl_prec).
355 #[inline]
356 pub fn shl_prec_ref<T: PrimitiveInt>(&self, bits: T, prec: u64) -> (Self, Ordering) {
357 self.shl_prec_round_ref(bits, prec, Nearest)
358 }
359
360 /// Left-shifts a [`Float`] (multiplies it by a power of 2) in place, rounding the result with
361 /// the specified precision.
362 ///
363 /// `NaN`, infinities, and zeros are unchanged. If the output has a precision, it is `prec`.
364 ///
365 /// $$
366 /// x \gets x2^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::shl_prec#shl_prec).
388 #[inline]
389 pub fn shl_prec_assign<T: PrimitiveInt>(&mut self, bits: T, prec: u64) -> Ordering {
390 self.shl_prec_round_assign(bits, prec, Nearest)
391 }
392}
393
394fn shl_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_add(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 left-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
459#[inline]
460fn shl_round_assign_primitive_int<T: PrimitiveInt>(
461 x: &mut Float,
462 bits: T,
463 rm: RoundingMode,
464) -> Ordering {
465 x.shl_prec_round_assign_helper(bits, x.significant_bits(), rm, Equal)
466}
467
468macro_rules! impl_natural_shl_round {
469 ($t:ident) => {
470 impl ShlRound<$t> for Float {
471 type Output = Float;
472
473 /// Left-shifts a [`Float`] (multiplies it by a power of 2), rounding the result with
474 /// the specified rounding mode and taking the [`Float`] by value.
475 ///
476 /// `NaN`, infinities, and zeros are unchanged. If the [`Float`] has a precision, the
477 /// output has the same precision.
478 ///
479 /// $$
480 /// f(x,k,m) = x2^k.
481 /// $$
482 ///
483 /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$
484 /// is returned instead.
485 /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`,
486 /// $(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the
487 /// input.
488 /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$
489 /// is returned instead.
490 /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`,
491 /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the
492 /// input.
493 /// - If $0<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned
494 /// instead.
495 /// - If $0<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is
496 /// returned instead.
497 /// - If $0<f(x,k,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
498 /// - If $2^{-2^{30}-1}<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is
499 /// returned instead.
500 /// - If $-2^{-2^{30}}<f(x,k,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
501 /// instead.
502 /// - If $-2^{-2^{30}}<f(x,k,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is
503 /// returned instead.
504 /// - If $-2^{-2^{30}-1}\leq f(x,k,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned
505 /// instead.
506 /// - If $-2^{-2^{30}}<f(x,k,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
507 /// returned instead.
508 ///
509 /// If you don't care about overflow or underflow behavior, or only want the behavior of
510 /// the `Nearest` rounding mode, you can just use `<<` instead.
511 ///
512 /// # Worst-case complexity
513 /// $T(n) = O(n)$
514 ///
515 /// $M(n) = O(n)$
516 ///
517 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
518 ///
519 /// # Panics
520 /// Panics if the result overflows or underflows and `rm` is `Exact`.
521 ///
522 /// # Examples
523 /// See [here](super::shl_round#shl_round).
524 #[inline]
525 fn shl_round(mut self, bits: $t, rm: RoundingMode) -> (Float, Ordering) {
526 let o = self.shl_round_assign(bits, rm);
527 (self, o)
528 }
529 }
530
531 impl ShlRound<$t> for &Float {
532 type Output = Float;
533
534 /// Left-shifts a [`Float`] (multiplies it by a power of 2), rounding the result with
535 /// the specified rounding mode and taking the [`Float`] by reference.
536 ///
537 /// `NaN`, infinities, and zeros are unchanged. If the [`Float`] has a precision, the
538 /// output has the same precision.
539 ///
540 /// $$
541 /// f(x,k,m) = x2^k.
542 /// $$
543 ///
544 /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$
545 /// is returned instead.
546 /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`,
547 /// $(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the
548 /// input.
549 /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$
550 /// is returned instead.
551 /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`,
552 /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the
553 /// input.
554 /// - If $0<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned
555 /// instead.
556 /// - If $0<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is
557 /// returned instead.
558 /// - If $0<f(x,k,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
559 /// - If $2^{-2^{30}-1}<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is
560 /// returned instead.
561 /// - If $-2^{-2^{30}}<f(x,k,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
562 /// instead.
563 /// - If $-2^{-2^{30}}<f(x,k,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is
564 /// returned instead.
565 /// - If $-2^{-2^{30}-1}\leq f(x,k,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned
566 /// instead.
567 /// - If $-2^{-2^{30}}<f(x,k,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
568 /// returned instead.
569 ///
570 /// If you don't care about overflow or underflow behavior, or only want the behavior of
571 /// the `Nearest` rounding mode, you can just use `<<` instead.
572 ///
573 /// # Worst-case complexity
574 /// $T(n) = O(n)$
575 ///
576 /// $M(n) = O(n)$
577 ///
578 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
579 ///
580 /// # Panics
581 /// Panics if the result overflows or underflows and `rm` is `Exact`.
582 ///
583 /// # Examples
584 /// See [here](super::shl_round#shl_round).
585 #[inline]
586 fn shl_round(self, bits: $t, rm: RoundingMode) -> (Float, Ordering) {
587 shl_round_primitive_int_ref(self, bits, rm)
588 }
589 }
590
591 impl ShlRoundAssign<$t> for Float {
592 /// Left-shifts a [`Float`] (multiplies it by a power of 2), in place, rounding the
593 /// result with the specified rounding mode.
594 ///
595 /// `NaN`, infinities, and zeros are unchanged. If the [`Float`] has a precision, the
596 /// precision is unchanged.
597 ///
598 /// $$
599 /// x\gets x2^k.
600 /// $$
601 ///
602 /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$
603 /// is returned instead.
604 /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`,
605 /// $(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the
606 /// input.
607 /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$
608 /// is returned instead.
609 /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`,
610 /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the
611 /// input.
612 /// - If $0<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned
613 /// instead.
614 /// - If $0<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is
615 /// returned instead.
616 /// - If $0<f(x,k,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
617 /// - If $2^{-2^{30}-1}<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is
618 /// returned instead.
619 /// - If $-2^{-2^{30}}<f(x,k,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
620 /// instead.
621 /// - If $-2^{-2^{30}}<f(x,k,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is
622 /// returned instead.
623 /// - If $-2^{-2^{30}-1}\leq f(x,k,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned
624 /// instead.
625 /// - If $-2^{-2^{30}}<f(x,k,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
626 /// returned instead.
627 ///
628 /// If you don't care about overflow or underflow behavior, or only want the behavior of
629 /// the `Nearest` rounding mode, you can just use `<<=` instead.
630 ///
631 /// # Worst-case complexity
632 /// $T(n) = O(n)$
633 ///
634 /// $M(n) = O(n)$
635 ///
636 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
637 ///
638 /// # Panics
639 /// Panics if the result overflows or underflows and `rm` is `Exact`.
640 ///
641 /// # Examples
642 /// See [here](super::shl_round#shl_round_assign).
643 #[inline]
644 fn shl_round_assign(&mut self, bits: $t, rm: RoundingMode) -> Ordering {
645 shl_round_assign_primitive_int(self, bits, rm)
646 }
647 }
648 };
649}
650apply_to_primitive_ints!(impl_natural_shl_round);