]>
Commit | Line | Data |
---|---|---|
49aad941 FG |
1 | use core::f64; |
2 | ||
3 | const TOINT: f64 = 1. / f64::EPSILON; | |
4 | ||
5 | /// Floor (f64) | |
6 | /// | |
7 | /// Finds the nearest integer less than or equal to `x`. | |
8 | #[inline] | |
9 | #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] | |
10 | pub fn floor(x: f64) -> f64 { | |
11 | // On wasm32 we know that LLVM's intrinsic will compile to an optimized | |
12 | // `f64.floor` native instruction, so we can leverage this for both code size | |
13 | // and speed. | |
14 | llvm_intrinsically_optimized! { | |
15 | #[cfg(target_arch = "wasm32")] { | |
16 | return unsafe { ::core::intrinsics::floorf64(x) } | |
17 | } | |
18 | } | |
19 | let ui = x.to_bits(); | |
20 | let e = ((ui >> 52) & 0x7ff) as i32; | |
21 | ||
22 | if (e >= 0x3ff + 52) || (x == 0.) { | |
23 | return x; | |
24 | } | |
25 | /* y = int(x) - x, where int(x) is an integer neighbor of x */ | |
26 | let y = if (ui >> 63) != 0 { | |
27 | x - TOINT + TOINT - x | |
28 | } else { | |
29 | x + TOINT - TOINT - x | |
30 | }; | |
31 | /* special case because of non-nearest rounding modes */ | |
32 | if e < 0x3ff { | |
33 | force_eval!(y); | |
34 | return if (ui >> 63) != 0 { -1. } else { 0. }; | |
35 | } | |
36 | if y > 0. { | |
37 | x + y - 1. | |
38 | } else { | |
39 | x + y | |
40 | } | |
41 | } |