jtempest / float_eq-rs

Compare IEEE floating point values for equality.
Other
39 stars 6 forks source link

Derived ulps_tol not usable in other modules because of private fields #24

Closed jacg closed 2 years ago

jacg commented 2 years ago

Here is an adaptation of the code shown in the documentation, which illustrates the problem

mod foo {
    use float_eq::*;

    #[derive_float_eq(
        ulps_tol = "PointUlps",
        ulps_tol_derive = "Clone, Copy, Debug, PartialEq",
        debug_ulps_diff = "PointUlpsDebugUlpsDiff",
        debug_ulps_diff_derive = "Clone, Copy, Debug, PartialEq",
        all_tol = "f64"
    )]
    #[derive(Debug, PartialEq, Clone, Copy)]
    pub struct Point {
        pub x: f64,
        pub y: f64,
    }

    #[cfg(test)]
    #[test]
    fn test_same_module() {
        let a = Point { x: 1.0, y: -2.0 };
        let c = Point {
            x: 1.000_000_000_000_000_9,
            y: -2.000_000_000_000_001_3
        };
        assert_float_eq!(a, c, ulps <= PointUlps { x: 4, y: 3 }); // Works
        assert_float_eq!(a, c, ulps_all <= 4);
    }
}

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

    #[test]
    fn test_other_module() {
        let a = Point { x: 1.0, y: -2.0 };
        let c = Point {
            x: 1.000_000_000_000_000_9,
            y: -2.000_000_000_000_001_3
        };
        assert_float_eq!(a, c, ulps <= PointUlps { x: 4, y: 3 }); // ERROR: x and y private
        assert_float_eq!(a, c, ulps_all <= 4);
    }
}

Both foo::Point and its x and y fields are public, so they can be used in other modules. However, the x and y fields of the derived PointUlps are private, preventing them from being used in other modules, which makes the whole of PointUlps unusable.

jtempest commented 2 years ago

Apologies for the very late reply, but thank you for the report. Currently working on a fix :).

jtempest commented 2 years ago

The visibility of derived fields in 1.0.1 should now match the original fields' visibility. Please let me know if there's anything else :)

jacg commented 2 years ago

This seems to be working fine now. Many thanks.

Going off on a tangent (let me know if there's a better place to raise this) ... I have a struct with a bunch of (lots, too many!) fields, and one or two of them are expected to be NaNs. I would like to be able to express a test along the lines of

Each of these fields should match within ulps <= 1 (or specific different ulpses for each) except these two which should be NaNs.

Is there any way of doing without writing a separate assertion for each member?