const_soft_float/soft_f64/
floor.rs1use super::{
2    helpers::{eq, gt},
3    SoftF64,
4};
5
6const TOINT: SoftF64 = SoftF64(1.0).div(SoftF64(f64::EPSILON));
7
8pub const fn floor(x: SoftF64) -> SoftF64 {
12    let ui = x.to_bits();
13    let e = ((ui >> 52) & 0x7ff) as i32;
14
15    if (e >= 0x3ff + 52) || eq(x, SoftF64::ZERO) {
16        return x;
17    }
18    let y = if (ui >> 63) != 0 {
20        x.sub(TOINT).add(TOINT).sub(x)
21    } else {
22        x.add(TOINT).sub(TOINT).sub(x)
23    };
24    if e < 0x3ff {
26        return if (ui >> 63) != 0 {
27            SoftF64(-1.0)
28        } else {
29            SoftF64::ZERO
30        };
31    }
32    if gt(y, SoftF64::ZERO) {
33        x.add(y).sub(SoftF64::ONE)
34    } else {
35        x.add(y)
36    }
37}
38
39#[cfg(test)]
40mod tests {
41    use super::*;
42
43    #[test]
44    fn sanity_check() {
45        assert_eq!(floor(SoftF64(1.1)).0, 1.0);
46        assert_eq!(floor(SoftF64(2.9)).0, 2.0);
47    }
48
49    #[test]
51    fn spec_tests() {
52        assert!(floor(SoftF64(f64::NAN)).0.is_nan());
54        for f in [0.0, -0.0, f64::INFINITY, f64::NEG_INFINITY]
55            .iter()
56            .copied()
57        {
58            assert_eq!(floor(SoftF64(f)).0, f);
59        }
60    }
61}