int-interval 0.8.1

A small, no_std half-open interval algebra library for primitive integer types.
Documentation
// -----------------------------------------------------------------------------
// @generated by xtask/codegen (signed)
// DO NOT EDIT MANUALLY.
// Changes will be overwritten.
// -----------------------------------------------------------------------------

use super::*;

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

    #[test]
    fn test_minkowski_add_basic() {
        let a = I16CO::try_new(1, 5).unwrap();
        let b = I16CO::try_new(-3, 2).unwrap();
        let res = a.checked_minkowski_add(b).unwrap();
        // start = 1 + -3 = -2
        assert_eq!(res.start(), -2);
        // end_excl = (4 + 1 + 1) = 6 (a.end_incl + b.end_incl + 1)
        assert_eq!(res.end_excl(), 6);
    }

    #[test]
    fn test_minkowski_sub_basic() {
        let a = I16CO::try_new(5, 10).unwrap();
        let b = I16CO::try_new(2, 4).unwrap();
        let res = a.checked_minkowski_sub(b).unwrap();
        assert_eq!(res.start(), 2); // 5 - 3
        assert_eq!(res.end_excl(), 8); // 9 - 2 + 1
    }

    #[test]
    fn test_minkowski_mul_basic() {
        let a = I16CO::try_new(-2, 3).unwrap(); // [-2,3)
        let b = I16CO::try_new(-1, 2).unwrap(); // [-1,2)
        let res = a.checked_minkowski_mul_hull(b).unwrap();
        // 四个组合: -2*-1=2, -2*1=-2, 2*-1=-2, 2*1=2 -> min=-2, max=2
        assert_eq!(res.start(), -2);
        assert_eq!(res.end_excl(), 3); // max+1=2+1
    }

    #[test]
    fn test_minkowski_div_basic() {
        let a = I16CO::try_new(-4, 10).unwrap();
        let b = I16CO::try_new(2, 5).unwrap();
        let res = a.checked_minkowski_div_hull(b).unwrap();
        // 四个组合:-4/2=-2, -4/4=-1, 9/2=4, 9/4=2 -> min=-2, max=4
        assert_eq!(res.start(), -2);
        assert_eq!(res.end_excl(), 5); // max+1=4+1
    }

    #[test]
    fn test_minkowski_div_by_zero() {
        let a = I16CO::try_new(1, 5).unwrap();
        let b = I16CO::try_new(0, 3).unwrap();
        assert!(a.checked_minkowski_div_hull(b).is_none());
    }
}

#[cfg(test)]
mod prop_tests {
    use super::*;
    use proptest::prelude::*;

    fn interval_strategy() -> impl Strategy<Value = I16CO> {
        prop_oneof![
            Just(I16CO::try_new(i16::MIN, i16::MIN + 1).unwrap()), // [-128, -127)
            Just(I16CO::try_new(i16::MIN, i16::MAX).unwrap()),     // [-128, 127)
            Just(I16CO::try_new(i16::MAX - 1, i16::MAX).unwrap()), // [126, 127)
            (i16::MIN..=i16::MAX, i16::MIN..=i16::MAX)
                .prop_filter_map("valid interval", |(s, e)| I16CO::try_new(s, e))
        ]
    }

    proptest! {
        #[test]
        fn prop_add_containment(a in interval_strategy(), b in interval_strategy()) {
            if let Some(c) = a.checked_minkowski_add(b) {
                let xs = [a.start(), a.end_excl()-1];
                let ys = [b.start(), b.end_excl()-1];
                for &x in &xs {
                    for &y in &ys {
                        let sum = x.wrapping_add(y);
                        prop_assert!(c.start() <= sum && sum < c.end_excl());
                    }
                }
            }
        }

        #[test]
        fn prop_sub_containment(a in interval_strategy(), b in interval_strategy()) {
            if let Some(c) = a.checked_minkowski_sub(b) {
                let xs = [a.start(), a.end_excl()-1];
                let ys = [b.start(), b.end_excl()-1];
                for &x in &xs {
                    for &y in &ys {
                        let diff = x.wrapping_sub(y);
                        prop_assert!(c.start() <= diff && diff < c.end_excl());
                    }
                }
            }
        }

        #[test]
        fn prop_mul_containment(a in interval_strategy(), b in interval_strategy()) {
            if let Some(c) = a.checked_minkowski_mul_hull(b) {
                let xs = [a.start(), a.end_excl()-1];
                let ys = [b.start(), b.end_excl()-1];
                for &x in &xs {
                    for &y in &ys {
                        let prod = x.wrapping_mul(y);
                        prop_assert!(c.start() <= prod && prod < c.end_excl());
                    }
                }
            }
        }

        #[test]
        fn prop_div_containment(a in interval_strategy(), b in interval_strategy()
            .prop_filter("non-zero start", |b| b.start() != 0)) {
            if let Some(c) = a.checked_minkowski_div_hull(b) {
                let xs = [a.start(), a.end_excl()-1];
                let ys = [b.start(), b.end_excl()-1];
                for &x in &xs {
                    for &y in &ys {
                        let div = x / y;
                        prop_assert!(c.start() <= div && div < c.end_excl());
                    }
                }
            }
        }

        #[test]
        fn prop_add_commutative(a in interval_strategy(), b in interval_strategy()) {
            let res1 = a.checked_minkowski_add(b);
            let res2 = b.checked_minkowski_add(a);
            prop_assert_eq!(res1, res2);
        }

        #[test]
        fn prop_mul_commutative(a in interval_strategy(), b in interval_strategy()) {
            let res1 = a.checked_minkowski_mul_hull(b);
            let res2 = b.checked_minkowski_mul_hull(a);
            prop_assert_eq!(res1, res2);
        }
    }
}