Coverage Report

Created: 2024-11-19 11:03

/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
24
pub fn floor(x: f64) -> f64 {
11
24
    // On wasm32 we know that LLVM's intrinsic will compile to an optimized
12
24
    // `f64.floor` native instruction, so we can leverage this for both code size
13
24
    // and speed.
14
24
    llvm_intrinsically_optimized! {
15
24
        #[cfg(target_arch = "wasm32")] {
16
24
            return unsafe { ::core::intrinsics::floorf64(x) }
17
24
        }
18
24
    }
19
24
    #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
20
24
    {
21
24
        //use an alternative implementation on x86, because the
22
24
        //main implementation fails with the x87 FPU used by
23
24
        //debian i386, probablly due to excess precision issues.
24
24
        //basic implementation taken from https://github.com/rust-lang/libm/issues/219
25
24
        use super::fabs;
26
24
        if fabs(x).to_bits() < 4503599627370496.0_f64.to_bits() {
27
24
            let truncated = x as i64 as f64;
28
24
            if truncated > x {
29
24
                return truncated - 1.0;
30
24
            } else {
31
24
                return truncated;
32
24
            }
33
24
        } else {
34
24
            return x;
35
24
        }
36
24
    }
37
24
    let ui = x.to_bits();
38
24
    let e = ((ui >> 52) & 0x7ff) as i32;
39
24
40
24
    if (e >= 0x3ff + 52) || 
(x == 0.)5
{
41
20
        return x;
42
4
    }
43
    /* y = int(x) - x, where int(x) is an integer neighbor of x */
44
4
    let y = if (ui >> 63) != 0 {
45
2
        x - TOINT + TOINT - x
46
    } else {
47
2
        x + TOINT - TOINT - x
48
    };
49
    /* special case because of non-nearest rounding modes */
50
4
    if e < 0x3ff {
51
1
        force_eval!(y);
52
1
        return if (ui >> 63) != 0 { -1. } else { 
0.0
};
53
3
    }
54
3
    if y > 0. {
55
1
        x + y - 1.
56
    } else {
57
2
        x + y
58
    }
59
24
}
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
}