// 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; }
void ra_free_without_containers(roaring_array_t *ra) { ra_clear_without_containers(ra); free(ra); }