int-interval 0.8.1

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

use super::*;

#[cfg(test)]
mod unit_tests {
    use core::usize;

    use super::*;

    #[test]
    fn test_saturating_minkowski_add_basic() {
        let a = UsizeCO::try_new(1, 5).unwrap();
        let b = UsizeCO::try_new(2, 4).unwrap();
        let res = a.saturating_minkowski_add(b).unwrap();
        assert_eq!(res.start(), 3);
        assert_eq!(res.end_excl(), 8);
    }

    #[test]
    fn test_saturating_minkowski_sub_basic() {
        let a = UsizeCO::try_new(5, 10).unwrap();
        let b = UsizeCO::try_new(2, 4).unwrap();
        let res = a.saturating_minkowski_sub(b).unwrap();
        assert_eq!(res.start(), 2);
        assert_eq!(res.end_excl(), 8);
    }

    #[test]
    fn test_saturating_minkowski_mul_basic() {
        let a = UsizeCO::try_new(1, 4).unwrap();
        let b = UsizeCO::try_new(2, 3).unwrap();
        let res = a.saturating_minkowski_mul_hull(b).unwrap();
        assert_eq!(res.start(), 2);
        assert_eq!(res.end_excl(), 7);
    }

    #[test]
    fn test_saturating_minkowski_div_basic() {
        let a = UsizeCO::try_new(4, 10).unwrap();
        let b = UsizeCO::try_new(2, 5).unwrap();
        let res = a.saturating_minkowski_div_hull(b).unwrap();
        assert_eq!(res.start(), 1);
        assert_eq!(res.end_excl(), 5);
    }

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

    #[test]
    fn test_saturating_add_can_collapse_to_none() {
        let a = UsizeCO::try_new(usize::MAX - 5, usize::MAX).unwrap(); // [250,255)
        let b = UsizeCO::try_new(10, 20).unwrap(); // [10,20)
        assert!(a.saturating_minkowski_add(b).is_none());
    }

    #[test]
    fn test_saturating_mul_can_collapse_to_none() {
        let a = UsizeCO::try_new(usize::MAX - 5, usize::MAX).unwrap();
        let b = UsizeCO::try_new(2, 3).unwrap();
        assert!(a.saturating_minkowski_mul_hull(b).is_none());
    }

    #[test]
    fn test_saturating_add_n_basic() {
        let a = UsizeCO::try_new(3, 7).unwrap();
        let res = a.saturating_minkowski_add_scalar(4).unwrap();
        assert_eq!(res, UsizeCO::try_new(7, 11).unwrap());
    }

    #[test]
    fn test_saturating_sub_n_basic() {
        let a = UsizeCO::try_new(7, 11).unwrap();
        let res = a.saturating_minkowski_sub_scalar(4).unwrap();
        assert_eq!(res, UsizeCO::try_new(3, 7).unwrap());
    }

    #[test]
    fn test_saturating_mul_n_basic() {
        let a = UsizeCO::try_new(2, 5).unwrap();
        let res = a.saturating_minkowski_mul_scalar_hull(3).unwrap();
        assert_eq!(res, UsizeCO::try_new(6, 13).unwrap());
    }

    #[test]
    fn test_saturating_div_n_basic() {
        let a = UsizeCO::try_new(6, 13).unwrap();
        let res = a.saturating_minkowski_div_scalar_hull(3).unwrap();
        assert_eq!(res, UsizeCO::try_new(2, 5).unwrap());
    }

    #[test]
    fn test_saturating_div_n_by_zero() {
        let a = UsizeCO::try_new(1, 5).unwrap();
        assert!(a.saturating_minkowski_div_scalar_hull(0).is_none());
    }

    #[test]
    fn test_saturating_add_n_can_collapse_to_none() {
        let a = UsizeCO::try_new(usize::MAX - 5, usize::MAX).unwrap();
        assert!(a.saturating_minkowski_add_scalar(10).is_none());
    }

    #[test]
    fn test_saturating_sub_n_can_collapse_to_none() {
        let a = UsizeCO::try_new(1, 3).unwrap();
        assert!(a.saturating_minkowski_sub_scalar(10).is_none());
    }

    #[test]
    fn test_saturating_mul_n_can_collapse_to_none() {
        let a = UsizeCO::try_new(usize::MAX - 5, usize::MAX).unwrap();
        assert!(a.saturating_minkowski_mul_scalar_hull(2).is_none());
    }
}

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

    fn interval_strategy() -> impl Strategy<Value = UsizeCO> {
        prop_oneof![
            Just(UsizeCO::try_new(usize::MIN, usize::MIN + 1).unwrap()), // [0,1)
            Just(UsizeCO::try_new(usize::MIN, usize::MAX).unwrap()),     // [0,255)
            Just(UsizeCO::try_new(usize::MAX - 1, usize::MAX).unwrap()), // [254,255)
            (usize::MIN..=usize::MAX, usize::MIN..=usize::MAX)
                .prop_filter_map("valid interval", |(s, e)| UsizeCO::try_new(s, e))
        ]
    }

    fn scalar_strategy() -> impl Strategy<Value = usize> {
        prop_oneof![Just(0), Just(1), Just(usize::MAX), any::<usize>()]
    }

    #[inline]
    fn endpoints(x: UsizeCO) -> [usize; 2] {
        [x.start(), x.end_incl()]
    }

    proptest! {
        #[test]
        fn prop_saturating_add_semantics(a in interval_strategy(), b in interval_strategy()) {
            let got = a.saturating_minkowski_add(b);

            let expect_start = a.start().saturating_add(b.start());
            let expect_end_excl = a.end_excl().saturating_add(b.end_incl());
            let expect_none = expect_start >= expect_end_excl;

            prop_assert_eq!(got.is_none(), expect_none);

            if let Some(c) = got {
                prop_assert_eq!(c.start(), expect_start);
                prop_assert_eq!(c.end_excl(), expect_end_excl);

                for &x in &endpoints(a) {
                    for &y in &endpoints(b) {
                        let z = x.saturating_add(y);
                        if z < c.end_excl() {
                            prop_assert!(c.contains(z));
                        } else {
                            prop_assert_eq!(z, usize::MAX);
                        }
                    }
                }
            }
        }

        #[test]
        fn prop_saturating_sub_semantics(a in interval_strategy(), b in interval_strategy()) {
            let got = a.saturating_minkowski_sub(b);

            let expect_none =
                a.start().saturating_sub(b.end_incl()) >=
                a.end_excl().saturating_sub(b.start());

            prop_assert_eq!(got.is_none(), expect_none);

            if let Some(c) = got {
                prop_assert_eq!(c.start(), a.start().saturating_sub(b.end_incl()));
                prop_assert_eq!(c.end_incl(), a.end_incl().saturating_sub(b.start()));

                for &x in &endpoints(a) {
                    for &y in &endpoints(b) {
                        let z = x.saturating_sub(y);
                        prop_assert!(c.contains(z));
                    }
                }
            }
        }

        #[test]
        fn prop_saturating_mul_semantics(a in interval_strategy(), b in interval_strategy()) {
            let got = a.saturating_minkowski_mul_hull(b);

            let expect_start = a.start().saturating_mul(b.start());
            let expect_end_excl = a.end_incl().saturating_mul(b.end_incl()).saturating_add(1);
            let expect_none = expect_start >= expect_end_excl;

            prop_assert_eq!(got.is_none(), expect_none);

            if let Some(c) = got {
                prop_assert_eq!(c.start(), expect_start);
                prop_assert_eq!(c.end_excl(), expect_end_excl);

                for &x in &endpoints(a) {
                    for &y in &endpoints(b) {
                        let z = x.saturating_mul(y);
                        if z < c.end_excl() {
                            prop_assert!(c.contains(z));
                        } else {
                            prop_assert_eq!(z, usize::MAX);
                        }
                    }
                }
            }
        }

        #[test]
        fn prop_saturating_div_semantics(
            a in interval_strategy(),
            b in interval_strategy()
        ) {
            let got = a.saturating_minkowski_div_hull(b);

            let expect_none =
                b.start() == 0 ||
                (a.start() / b.end_incl()) >= (a.end_incl() / b.start()).saturating_add(1);

            prop_assert_eq!(got.is_none(), expect_none);

            if let Some(c) = got {
                prop_assert!(b.start() != 0);
                prop_assert_eq!(c.start(), a.start() / b.end_incl());
                prop_assert_eq!(c.end_incl(), a.end_incl() / b.start());

                for &x in &endpoints(a) {
                    for &y in &endpoints(b) {
                        if y == 0 {
                            continue;
                        }
                        let z = x / y;
                        prop_assert!(c.contains(z));
                    }
                }
            }
        }

        #[test]
        fn prop_saturating_add_n_semantics(a in interval_strategy(), n in scalar_strategy()) {
            let got = a.saturating_minkowski_add_scalar(n);

            let expect_start = a.start().saturating_add(n);
            let expect_end_excl = a.end_excl().saturating_add(n);
            let expect_none = expect_start >= expect_end_excl;

            prop_assert_eq!(got.is_none(), expect_none);

            if let Some(c) = got {
                prop_assert_eq!(c.start(), expect_start);
                prop_assert_eq!(c.end_excl(), expect_end_excl);

                for &x in &endpoints(a) {
                    let z = x.saturating_add(n);
                    if z < c.end_excl() {
                        prop_assert!(c.contains(z));
                    } else {
                        prop_assert_eq!(z, usize::MAX);
                    }
                }
            }
        }

        #[test]
        fn prop_saturating_sub_n_semantics(a in interval_strategy(), n in scalar_strategy()) {
            let got = a.saturating_minkowski_sub_scalar(n);

            let expect_none =
                a.start().saturating_sub(n) >= a.end_excl().saturating_sub(n);

            prop_assert_eq!(got.is_none(), expect_none);

            if let Some(c) = got {
                prop_assert_eq!(c.start(), a.start().saturating_sub(n));
                prop_assert_eq!(c.end_incl(), a.end_incl().saturating_sub(n));

                for &x in &endpoints(a) {
                    let z = x.saturating_sub(n);
                    prop_assert!(c.contains(z));
                }
            }
        }

        #[test]
        fn prop_saturating_mul_n_semantics(a in interval_strategy(), n in scalar_strategy()) {
            let got = a.saturating_minkowski_mul_scalar_hull(n);

            let expect_start = a.start().saturating_mul(n);
            let expect_end_excl = a.end_incl().saturating_mul(n).saturating_add(1);
            let expect_none = expect_start >= expect_end_excl;

            prop_assert_eq!(got.is_none(), expect_none);

            if let Some(c) = got {
                prop_assert_eq!(c.start(), expect_start);
                prop_assert_eq!(c.end_excl(), expect_end_excl);

                for &x in &endpoints(a) {
                    let z = x.saturating_mul(n);
                    if z < c.end_excl() {
                        prop_assert!(c.contains(z));
                    } else {
                        prop_assert_eq!(z, usize::MAX);
                    }
                }
            }
        }

        #[test]
        fn prop_saturating_div_n_semantics(a in interval_strategy(), n in scalar_strategy()) {
            let got = a.saturating_minkowski_div_scalar_hull(n);

            let expect_none =
                n == 0 ||
                (a.start() / n) >= (a.end_incl() / n).saturating_add(1);

            prop_assert_eq!(got.is_none(), expect_none);

            if let Some(c) = got {
                prop_assert!(n != 0);
                prop_assert_eq!(c.start(), a.start() / n);
                prop_assert_eq!(c.end_incl(), a.end_incl() / n);

                for &x in &endpoints(a) {
                    let z = x / n;
                    prop_assert!(c.contains(z));
                }
            }
        }

        #[test]
        fn prop_add_commutative(a in interval_strategy(), b in interval_strategy()) {
            prop_assert_eq!(a.saturating_minkowski_add(b), b.saturating_minkowski_add(a));
        }

        #[test]
        fn prop_mul_commutative(a in interval_strategy(), b in interval_strategy()) {
            prop_assert_eq!(a.saturating_minkowski_mul_hull(b), b.saturating_minkowski_mul_hull(a));
        }
    }
}