int contains_test(run_container_t* B) {
    int card = 0;
    int x;
    for (x = 0; x < (1 << 16); x++) {
        card += run_container_contains(B, (uint16_t)x);
    }
    return card;
}
Exemplo n.º 2
0
void add_contains_test() {
    run_container_t* B = run_container_create();
    assert_non_null(B);

    int expected_card = 0;
    for (size_t x = 0; x < 1 << 16; x += 3) {
        assert_true(run_container_add(B, x));
        assert_true(run_container_contains(B, x));
        assert_int_equal(run_container_cardinality(B), ++expected_card);
        assert_true(run_container_cardinality(B) <= B->capacity);
    }

    for (size_t x = 0; x < 1 << 16; x++) {
        assert_int_equal(run_container_contains(B, x), (x / 3 * 3 == x));
    }

    assert_int_equal(run_container_cardinality(B), (1 << 16) / 3 + 1);

    for (size_t x = 0; x < 1 << 16; x += 3) {
        assert_true(run_container_contains(B, x));
        assert_true(run_container_remove(B, x));
        assert_int_equal(run_container_cardinality(B), --expected_card);
        assert_false(run_container_contains(B, x));
    }

    assert_int_equal(run_container_cardinality(B), 0);

    for (int x = 65535; x >= 0; x -= 3) {
        assert_true(run_container_add(B, x));
        assert_true(run_container_contains(B, x));
        assert_int_equal(run_container_cardinality(B), ++expected_card);
        assert_true(run_container_cardinality(B) <= B->capacity);
    }

    assert_int_equal(run_container_cardinality(B), (1 << 16) / 3 + 1);

    for (size_t x = 0; x < 1 << 16; x++) {
        assert_int_equal(run_container_contains(B, x), (x / 3 * 3 == x));
    }

    for (size_t x = 0; x < 1 << 16; x += 3) {
        assert_true(run_container_contains(B, x));
        assert_true(run_container_remove(B, x));
        assert_int_equal(run_container_cardinality(B), --expected_card);
        assert_false(run_container_contains(B, x));
    }

    run_container_free(B);
}
Exemplo n.º 3
0
/*
 * Same as run_container_negation except that if the output is to
 * be a
 * run_container_t, and has the capacity to hold the result,
 * then src is modified and no allocation is made.
 * In all cases, the result is in *dst.
 */
int run_container_negation_range_inplace(run_container_t *src,
                                         const int range_start,
                                         const int range_end, void **dst) {
    uint8_t return_typecode;

    if (range_end <= range_start) {
        *dst = src;
        return RUN_CONTAINER_TYPE_CODE;
    }

    // TODO: efficient special case when range is 0 to 65535 inclusive

    if (src->capacity == src->n_runs) {
        // no excess room.  More checking to see if result can fit
        bool last_val_before_range = false;
        bool first_val_in_range = false;
        bool last_val_in_range = false;
        bool first_val_past_range = false;

        if (range_start > 0)
            last_val_before_range =
                run_container_contains(src, (uint16_t)(range_start - 1));
        first_val_in_range = run_container_contains(src, (uint16_t)range_start);

        if (last_val_before_range == first_val_in_range) {
            last_val_in_range =
                run_container_contains(src, (uint16_t)(range_end - 1));
            if (range_end != 0x10000)
                first_val_past_range =
                    run_container_contains(src, (uint16_t)range_end);

            if (last_val_in_range ==
                first_val_past_range) {  // no space for inplace
                int ans = run_container_negation_range(src, range_start,
                                                       range_end, dst);
                run_container_free(src);
                return ans;
            }
        }
    }
    // all other cases: result will fit

    run_container_t *ans = src;
    int my_nbr_runs = src->n_runs;

    ans->n_runs = 0;
    int k = 0;
    for (; (k < my_nbr_runs) && (src->runs[k].value < range_start); ++k) {
        // ans->runs[k] = src->runs[k]; (would be self-copy)
        ans->n_runs++;
    }

    // as with Java implementation, use locals to give self a buffer of depth 1
    rle16_t buffered = (rle16_t){.value = (uint16_t)0, .length = (uint16_t)0};
    rle16_t next = buffered;
    if (k < my_nbr_runs) buffered = src->runs[k];

    run_container_smart_append_exclusive(
        ans, (uint16_t)range_start, (uint16_t)(range_end - range_start - 1));

    for (; k < my_nbr_runs; ++k) {
        if (k + 1 < my_nbr_runs) next = src->runs[k + 1];

        run_container_smart_append_exclusive(ans, buffered.value,
                                             buffered.length);
        buffered = next;
    }

    *dst = convert_run_to_efficient_container(ans, &return_typecode);
    if (return_typecode != RUN_CONTAINER_TYPE_CODE) run_container_free(ans);

    return return_typecode;
}