libfl 0.0.1

Library for floating point operations that supports rounding modes and fpu exceptions
Documentation
#[derive(Debug)]
#[repr(C)]
pub enum RoundingMode {
    ToNearest = 0,
    TowardZero = 1,
    Upward = 2,
    Downward = 3,
}

#[derive(Debug, PartialEq)]
#[repr(C)]
pub enum Exception {
    None = 0,
    DivByZero = 1 << 0,
    Invalid = 1 << 1,
    Overflow = 1 << 2,
    Underflow = 1 << 3,
    Inexact = 1 << 4,
}

#[repr(C)]
struct Result32 {
    value: f32,
    exception: Exception,
}

impl Result32 {
    fn new() -> Self {
        Self {
            value: 0.0,
            exception: Exception::None,
        }
    }
}

mod ffi {
    use super::Result32;

    extern "C" {
        pub fn f32_div(
            a: cty::c_float,
            b: cty::c_float,
            rm: cty::c_uint,
            out: *mut Result32,
        ) -> cty::c_void;
    }
}

pub fn f32_div(a: f32, b: f32, rm: RoundingMode) -> (f32, Exception) {
    let mut result = Result32::new();
    unsafe { ffi::f32_div(a, b, rm as cty::c_uint, &mut result) };
    (result.value, result.exception)
}


#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_f32_div() {
        let (r_1, exc_1) = f32_div(10.0f32, 2.0f32, RoundingMode::ToNearest);
        assert_eq!(r_1, 5.0f32);
        assert_eq!(exc_1, Exception::None);
    }

    #[test]
    fn test_f32_div_rm_tonearest() {
        let (r_1, _) = f32_div(1f32, 2.1f32, RoundingMode::ToNearest);
        assert_eq!(r_1, 0.4761905f32);
    }

    #[test]
    fn test_f32_div_rm_towardzero() {
        let (r_1, _) = f32_div(1f32, 2.1f32, RoundingMode::TowardZero);
        assert_eq!(r_1, 0.47619048f32);
    }

    #[test]
    fn test_f32_div_rm_upward() {
        let (r_1, _) = f32_div(1f32, 2.1f32, RoundingMode::Upward);
        assert_eq!(r_1, 0.4761905f32);
    }

    #[test]
    fn test_f32_div_rm_downward() {
        let (r_1, _) = f32_div(1f32, 2.1f32, RoundingMode::Downward);
        assert_eq!(r_1, 0.47619048f32);
    }

    #[test]
    fn test_f32_div_exc_inexact() {
        let (r_1, exc_1) = f32_div(1f32, 2.1f32, RoundingMode::ToNearest);
        assert_eq!(r_1, 0.4761905f32);
        assert_eq!(exc_1, Exception::Inexact);
    }

    #[test]
    fn test_f32_div_exc_byzero() {
        let (r_1, exc_1) = f32_div(1f32, 0.0f32, RoundingMode::ToNearest);
        assert_eq!(r_1.is_infinite(), true);
        assert_eq!(exc_1, Exception::DivByZero);
    }
}