1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
use super::SoftF32;
/// Floor (SoftF32)
///
/// Finds the nearest integer less than or equal to `x`.
pub const fn floor(x: SoftF32) -> SoftF32 {
let mut ui = x.to_bits();
let e = (((ui >> 23) as i32) & 0xff) - 0x7f;
if e >= 23 {
return x;
}
if e >= 0 {
let m: u32 = 0x007fffff >> e;
if (ui & m) == 0 {
return x;
}
// force_eval!(x + SoftF32::from_bits(0x7b800000));
if ui >> 31 != 0 {
ui += m;
}
ui &= !m;
} else {
// force_eval!(x + SoftF32::from_bits(0x7b800000));
if ui >> 31 == 0 {
ui = 0;
} else if ui << 1 != 0 {
return SoftF32(-1.0);
}
}
SoftF32::from_bits(ui)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sanity_check() {
assert_eq!(floor(SoftF32(0.5)).0, 0.0);
assert_eq!(floor(SoftF32(1.1)).0, 1.0);
assert_eq!(floor(SoftF32(2.9)).0, 2.0);
}
/// The spec: https://en.cppreference.com/w/cpp/numeric/math/floor
#[test]
fn spec_tests() {
// Not Asserted: that the current rounding mode has no effect.
assert!(floor(SoftF32(f32::NAN)).0.is_nan());
for f in [0.0, -0.0, f32::INFINITY, f32::NEG_INFINITY]
.iter()
.copied()
{
assert_eq!(SoftF32(f).floor().0, f);
}
}
}