| 1 | #[cfg_attr (all(test, assert_no_panic), no_panic::no_panic)] |
| 2 | pub fn scalbn(x: f64, mut n: i32) -> f64 { |
| 3 | let x1p1023 = f64::from_bits(0x7fe0000000000000); // 0x1p1023 === 2 ^ 1023 |
| 4 | let x1p53 = f64::from_bits(0x4340000000000000); // 0x1p53 === 2 ^ 53 |
| 5 | let x1p_1022 = f64::from_bits(0x0010000000000000); // 0x1p-1022 === 2 ^ (-1022) |
| 6 | |
| 7 | let mut y = x; |
| 8 | |
| 9 | if n > 1023 { |
| 10 | y *= x1p1023; |
| 11 | n -= 1023; |
| 12 | if n > 1023 { |
| 13 | y *= x1p1023; |
| 14 | n -= 1023; |
| 15 | if n > 1023 { |
| 16 | n = 1023; |
| 17 | } |
| 18 | } |
| 19 | } else if n < -1022 { |
| 20 | /* make sure final n < -53 to avoid double |
| 21 | rounding in the subnormal range */ |
| 22 | y *= x1p_1022 * x1p53; |
| 23 | n += 1022 - 53; |
| 24 | if n < -1022 { |
| 25 | y *= x1p_1022 * x1p53; |
| 26 | n += 1022 - 53; |
| 27 | if n < -1022 { |
| 28 | n = -1022; |
| 29 | } |
| 30 | } |
| 31 | } |
| 32 | y * f64::from_bits(((0x3ff + n) as u64) << 52) |
| 33 | } |
| 34 | |