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 #[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)] 9 pub fn floor(x: f64) -> f64 { 10 // On wasm32 we know that LLVM's intrinsic will compile to an optimized 11 // `f64.floor` native instruction, so we can leverage this for both code size fdimf(x: f32, y: f32) -> f3212 // and speed. 13 llvm_intrinsically_optimized! { 14 #[cfg(target_arch = "wasm32")] { 15 return unsafe { ::core::intrinsics::floorf64(x) } 16 } 17 } 18 let ui = x.to_bits(); 19 let e = ((ui >> 52) & 0x7ff) as i32; 20 21 if (e >= 0x3ff + 52) || (x == 0.) { 22 return x; 23 } 24 /* y = int(x) - x, where int(x) is an integer neighbor of x */ 25 let y = if (ui >> 63) != 0 { 26 x - TOINT + TOINT - x 27 } else { 28 x + TOINT - TOINT - x 29 }; 30 /* special case because of non-nearest rounding modes */ 31 if e < 0x3ff { 32 force_eval!(y); 33 return if (ui >> 63) != 0 { -1. } else { 0. }; 34 } 35 if y > 0. { 36 x + y - 1. 37 } else { 38 x + y 39 } 40 } 41 42 #[cfg(test)] 43 mod tests { 44 use super::*; 45 use core::f64::*; 46 47 #[test] 48 fn sanity_check() { 49 assert_eq!(floor(1.1), 1.0); 50 assert_eq!(floor(2.9), 2.0); 51 } 52 53 /// The spec: https://en.cppreference.com/w/cpp/numeric/math/floor 54 #[test] 55 fn spec_tests() { 56 // Not Asserted: that the current rounding mode has no effect. 57 assert!(floor(NAN).is_nan()); 58 for f in [0.0, -0.0, INFINITY, NEG_INFINITY].iter().copied() { 59 assert_eq!(floor(f), f); 60 } 61 } 62 } 63