Пример #1
0
// this function consumes and frees the inputs
static roaring_bitmap_t *lazy_or_from_lazy_inputs(roaring_bitmap_t *x1,
                                                  roaring_bitmap_t *x2) {
    uint8_t container_result_type = 0;
    const int length1 = ra_get_size(&x1->high_low_container),
              length2 = ra_get_size(&x2->high_low_container);
    if (0 == length1) {
        roaring_bitmap_free(x1);
        return x2;
    }
    if (0 == length2) {
        roaring_bitmap_free(x2);
        return x1;
    }
    uint32_t neededcap = length1 > length2 ? length2 : length1;
    roaring_bitmap_t *answer = roaring_bitmap_create_with_capacity(neededcap);
    int pos1 = 0, pos2 = 0;
    uint8_t container_type_1, container_type_2;
    uint16_t s1 = ra_get_key_at_index(&x1->high_low_container, pos1);
    uint16_t s2 = ra_get_key_at_index(&x2->high_low_container, pos2);
    while (true) {
        if (s1 == s2) {
            // todo: unsharing can be inefficient as it may create a clone where
            // none
            // is needed, but it has the benefit of being easy to reason about.
            ra_unshare_container_at_index(&x1->high_low_container, pos1);
            void *c1 = ra_get_container_at_index(&x1->high_low_container, pos1,
                                                 &container_type_1);
            assert(container_type_1 != SHARED_CONTAINER_TYPE_CODE);
            ra_unshare_container_at_index(&x2->high_low_container, pos2);
            void *c2 = ra_get_container_at_index(&x2->high_low_container, pos2,
                                                 &container_type_2);
            assert(container_type_2 != SHARED_CONTAINER_TYPE_CODE);
            void *c;

            if ((container_type_2 == BITSET_CONTAINER_TYPE_CODE) &&
                (container_type_1 != BITSET_CONTAINER_TYPE_CODE)) {
                c = container_lazy_ior(c2, container_type_2, c1,
                                       container_type_1,
                                       &container_result_type);
                container_free(c1, container_type_1);
                if (c != c2) {
                    container_free(c2, container_type_2);
                }
            } else {
                c = container_lazy_ior(c1, container_type_1, c2,
                                       container_type_2,
                                       &container_result_type);
                container_free(c2, container_type_2);
                if (c != c1) {
                    container_free(c1, container_type_1);
                }
            }
            // since we assume that the initial containers are non-empty, the
            // result here
            // can only be non-empty
            ra_append(&answer->high_low_container, s1, c,
                      container_result_type);
            ++pos1;
            ++pos2;
            if (pos1 == length1) break;
            if (pos2 == length2) break;
            s1 = ra_get_key_at_index(&x1->high_low_container, pos1);
            s2 = ra_get_key_at_index(&x2->high_low_container, pos2);

        } else if (s1 < s2) {  // s1 < s2
            void *c1 = ra_get_container_at_index(&x1->high_low_container, pos1,
                                                 &container_type_1);
            ra_append(&answer->high_low_container, s1, c1, container_type_1);
            pos1++;
            if (pos1 == length1) break;
            s1 = ra_get_key_at_index(&x1->high_low_container, pos1);

        } else {  // s1 > s2
            void *c2 = ra_get_container_at_index(&x2->high_low_container, pos2,
                                                 &container_type_2);
            ra_append(&answer->high_low_container, s2, c2, container_type_2);
            pos2++;
            if (pos2 == length2) break;
            s2 = ra_get_key_at_index(&x2->high_low_container, pos2);
        }
    }
    if (pos1 == length1) {
        ra_append_move_range(&answer->high_low_container,
                             &x2->high_low_container, pos2, length2);
    } else if (pos2 == length2) {
        ra_append_move_range(&answer->high_low_container,
                             &x1->high_low_container, pos1, length1);
    }
    ra_clear_without_containers(&x1->high_low_container);
    ra_clear_without_containers(&x2->high_low_container);
    free(x1);
    free(x2);
    return answer;
}
Пример #2
0
void ra_free_without_containers(roaring_array_t *ra) {
    ra_clear_without_containers(ra);
    free(ra);
}