1 | use core::f64; |
2 | |
3 | #[cfg_attr (all(test, assert_no_panic), no_panic::no_panic)] |
4 | pub fn trunc(x: f64) -> f64 { |
5 | // On wasm32 we know that LLVM's intrinsic will compile to an optimized |
6 | // `f64.trunc` native instruction, so we can leverage this for both code size |
7 | // and speed. |
8 | llvm_intrinsically_optimized! { |
9 | #[cfg(target_arch = "wasm32" )] { |
10 | return unsafe { ::core::intrinsics::truncf64(x) } |
11 | } |
12 | } |
13 | let x1p120 = f64::from_bits(0x4770000000000000); // 0x1p120f === 2 ^ 120 |
14 | |
15 | let mut i: u64 = x.to_bits(); |
16 | let mut e: i64 = (i >> 52 & 0x7ff) as i64 - 0x3ff + 12; |
17 | let m: u64; |
18 | |
19 | if e >= 52 + 12 { |
20 | return x; |
21 | } |
22 | if e < 12 { |
23 | e = 1; |
24 | } |
25 | m = -1i64 as u64 >> e; |
26 | if (i & m) == 0 { |
27 | return x; |
28 | } |
29 | force_eval!(x + x1p120); |
30 | i &= !m; |
31 | f64::from_bits(i) |
32 | } |
33 | |
34 | #[cfg (test)] |
35 | mod tests { |
36 | #[test ] |
37 | fn sanity_check() { |
38 | assert_eq!(super::trunc(1.1), 1.0); |
39 | } |
40 | } |
41 | |