int-interval-set 0.2.0

Integer half-open interval set structures built on top of int-interval.
Documentation
// -----------------------------------------------------------------------------
// This file is generated by `cargo run -p codegen -- --signed`.
// Do not edit manually.
// -----------------------------------------------------------------------------

use crate::i128::tests::{
    set::test_support::build,
    test_support::{build_from_vec, interval_pair, iv},
};

#[test]
fn coverage_empty_set_has_zero_covered_len() {
    let set = build([]);

    let query = iv(10, 20);

    assert_eq!(set.covered_len(query), 0);
    assert_eq!(set.uncovered_len(query), query.len());
    assert_eq!(set.coverage_ratio(query), 0.0);
}

#[test]
fn coverage_full_cover_has_full_covered_len() {
    let set = build([(10, 20)]);

    let query = iv(10, 20);

    assert_eq!(set.covered_len(query), 10);
    assert_eq!(set.uncovered_len(query), 0);
    assert_eq!(set.coverage_ratio(query), 1.0);
}

#[test]
fn coverage_partial_cover_inside_single_interval() {
    let set = build([(10, 20)]);

    let query = iv(15, 25);

    assert_eq!(set.covered_len(query), 5);
    assert_eq!(set.uncovered_len(query), 5);
    assert_eq!(set.coverage_ratio(query), 0.5);
}

#[test]
fn coverage_gap_only_query_has_zero_covered_len() {
    let set = build([(10, 20), (30, 40)]);

    let query = iv(20, 30);

    assert_eq!(set.covered_len(query), 0);
    assert_eq!(set.uncovered_len(query), 10);
    assert_eq!(set.coverage_ratio(query), 0.0);
}

#[test]
fn coverage_across_multiple_intervals() {
    let set = build([(-50, -40), (-20, -10), (10, 20)]);

    let query = iv(-45, 15);

    assert_eq!(
        set.intersections(query).collect::<Vec<_>>(),
        vec![iv(-45, -40), iv(-20, -10), iv(10, 15)]
    );

    assert_eq!(set.covered_len(query), 20);
    assert_eq!(set.uncovered_len(query), 40);
    assert_eq!(set.coverage_ratio(query), 20.0 / 60.0);
}

#[test]
fn coverage_uses_canonical_merged_intervals() {
    let set = build([(-20, -15), (-15, -10), (-5, 5), (0, 10)]);

    assert_eq!(set.as_slice(), &[iv(-20, -10), iv(-5, 10)]);

    let query = iv(-12, 0);

    assert_eq!(
        set.intersections(query).collect::<Vec<_>>(),
        vec![iv(-12, -10), iv(-5, 0)]
    );

    assert_eq!(set.covered_len(query), 7);
    assert_eq!(set.uncovered_len(query), 5);
    assert_eq!(set.coverage_ratio(query), 7.0 / 12.0);
}

#[test]
fn coverage_query_containing_all_intervals() {
    let set = build([(10, 20), (30, 40)]);

    let query = iv(0, 50);

    assert_eq!(set.covered_len(query), 20);
    assert_eq!(set.uncovered_len(query), 30);
    assert_eq!(set.coverage_ratio(query), 0.4);
}

#[test]
fn coverage_handles_domain_edges() {
    let set = build([(i128::MIN, i128::MIN + 1), (i128::MAX - 1, i128::MAX)]);

    let left_query = iv(i128::MIN, i128::MIN + 2);
    let right_query = iv(i128::MAX - 2, i128::MAX);

    assert_eq!(set.covered_len(left_query), 1);
    assert_eq!(set.uncovered_len(left_query), 1);
    assert_eq!(set.coverage_ratio(left_query), 0.5);

    assert_eq!(set.covered_len(right_query), 1);
    assert_eq!(set.uncovered_len(right_query), 1);
    assert_eq!(set.coverage_ratio(right_query), 0.5);
}

#[test]
fn coverage_lengths_add_up_to_query_len() {
    let set = build([(10, 20), (30, 40), (50, 60)]);

    for query in [
        iv(0, 10),
        iv(9, 11),
        iv(15, 35),
        iv(20, 30),
        iv(35, 55),
        iv(55, 61),
        iv(i128::MIN, i128::MIN + 1),
        iv(i128::MAX - 1, i128::MAX),
    ] {
        assert_eq!(
            set.covered_len(query) + set.uncovered_len(query),
            query.len(),
            "query = {query:?}"
        );
    }
}

#[test]
fn coverage_ratio_matches_covered_len_over_query_len() {
    let set = build([(10, 20), (30, 40), (50, 60)]);

    for query in [
        iv(0, 10),
        iv(9, 11),
        iv(15, 35),
        iv(20, 30),
        iv(35, 55),
        iv(55, 61),
        iv(i128::MIN, i128::MIN + 1),
        iv(i128::MAX - 1, i128::MAX),
    ] {
        let expected = set.covered_len(query) as f32 / query.len() as f32;

        assert_eq!(set.coverage_ratio(query), expected, "query = {query:?}");
    }
}

use proptest::prelude::*;

proptest! {
    #[test]
    fn prop_coverage_lengths_partition_query(
        xs in prop::collection::vec(interval_pair(), 0..64),
        query in interval_pair(),
    ) {
        let set = build_from_vec(xs);
        let query = iv(query.0, query.1);

        prop_assert_eq!(
            set.covered_len(query) + set.uncovered_len(query),
            query.len()
        );
    }

    #[test]
    fn prop_covered_len_matches_intersection_predicate(
        xs in prop::collection::vec(interval_pair(), 0..64),
        query in interval_pair(),
    ) {
        let set = build_from_vec(xs);
        let query = iv(query.0, query.1);

        prop_assert_eq!(
            set.covered_len(query) > 0,
            set.intersects_interval(query)
        );
    }
}