Coverage Report

Created: 2024-09-10 12:50

/build/cargo-vendor-dir/libm-0.2.8/src/math/floor.rs
Line
Count
Source (jump to first uncovered line)
1
#![allow(unreachable_code)]
2
use core::f64;
3
4
const TOINT: f64 = 1. / f64::EPSILON;
5
6
/// Floor (f64)
7
///
8
/// Finds the nearest integer less than or equal to `x`.
9
#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
10
3
pub fn floor(x: f64) -> f64 {
11
3
    // On wasm32 we know that LLVM's intrinsic will compile to an optimized
12
3
    // `f64.floor` native instruction, so we can leverage this for both code size
13
3
    // and speed.
14
3
    llvm_intrinsically_optimized! {
15
3
        #[cfg(target_arch = "wasm32")] {
16
3
            return unsafe { ::core::intrinsics::floorf64(x) }
17
3
        }
18
3
    }
19
3
    #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
20
3
    {
21
3
        //use an alternative implementation on x86, because the
22
3
        //main implementation fails with the x87 FPU used by
23
3
        //debian i386, probablly due to excess precision issues.
24
3
        //basic implementation taken from https://github.com/rust-lang/libm/issues/219
25
3
        use super::fabs;
26
3
        if fabs(x).to_bits() < 4503599627370496.0_f64.to_bits() {
27
3
            let truncated = x as i64 as f64;
28
3
            if truncated > x {
29
3
                return truncated - 1.0;
30
3
            } else {
31
3
                return truncated;
32
3
            }
33
3
        } else {
34
3
            return x;
35
3
        }
36
3
    }
37
3
    let ui = x.to_bits();
38
3
    let e = ((ui >> 52) & 0x7ff) as i32;
39
3
40
3
    if (e >= 0x3ff + 52) || (x == 0.) {
41
0
        return x;
42
3
    }
43
    /* y = int(x) - x, where int(x) is an integer neighbor of x */
44
3
    let y = if (ui >> 63) != 0 {
45
2
        x - TOINT + TOINT - x
46
    } else {
47
1
        x + TOINT - TOINT - x
48
    };
49
    /* special case because of non-nearest rounding modes */
50
3
    if e < 0x3ff {
51
1
        force_eval!(y);
52
1
        return if (ui >> 63) != 0 { -1. } else { 
0.0
};
53
2
    }
54
2
    if y > 0. {
55
1
        x + y - 1.
56
    } else {
57
1
        x + y
58
    }
59
3
}
60
61
#[cfg(test)]
62
mod tests {
63
    use super::*;
64
    use core::f64::*;
65
66
    #[test]
67
    fn sanity_check() {
68
        assert_eq!(floor(1.1), 1.0);
69
        assert_eq!(floor(2.9), 2.0);
70
    }
71
72
    /// The spec: https://en.cppreference.com/w/cpp/numeric/math/floor
73
    #[test]
74
    fn spec_tests() {
75
        // Not Asserted: that the current rounding mode has no effect.
76
        assert!(floor(NAN).is_nan());
77
        for f in [0.0, -0.0, INFINITY, NEG_INFINITY].iter().copied() {
78
            assert_eq!(floor(f), f);
79
        }
80
    }
81
}