1const SIG_BITS: u32 = 52;
11const BITS: u32 = 64;
12const EXP_BITS: u32 = BITS - SIG_BITS - 1;
13const EXP_SAT: u32 = (1 << EXP_BITS) - 1;
14const EXP_BIAS: u32 = EXP_SAT >> 1;
15const SIG_MASK: u64 = 4503599627370495;
16
17pub const fn floor(x: f64) -> f64 {
18 nightly_exp!(floor, floor_inner, x)
19}
20
21const fn floor_inner(x: f64) -> f64 {
22 let zero = 0;
23
24 let mut ix = x.to_bits();
25 let e = exp_unbiased(x);
26
27 if e >= SIG_BITS as i32 {
29 return x;
30 }
31
32 if e >= 0 {
33 let m = SIG_MASK >> unsigned(e);
35 if ix & m == zero {
36 return x;
38 }
39
40 if x.is_sign_negative() {
41 ix += m;
42 }
43
44 ix &= !m;
45 f64::from_bits(ix)
46 } else if x.is_sign_positive() {
47 0.0
49 } else if ix << 1 != zero {
50 -1.0
52 } else {
53 x
55 }
56}
57
58const fn ex(x: f64) -> u32 {
59 (x.to_bits() >> SIG_BITS) as u32 & EXP_SAT
60}
61
62const fn signed(x: u32) -> i32 {
63 x as i32
64}
65
66const fn unsigned(x: i32) -> u32 {
67 x as u32
68}
69
70const fn exp_unbiased(x: f64) -> i32 {
71 signed(ex(x)) - EXP_BIAS as i32
72}