bool array_array_container_union(const array_container_t *src_1, const array_container_t *src_2, void **dst) { int totalCardinality = src_1->cardinality + src_2->cardinality; if (totalCardinality <= DEFAULT_MAX_SIZE) { *dst = array_container_create_given_capacity(totalCardinality); if (*dst != NULL) array_container_union(src_1, src_2, (array_container_t *)*dst); return false; // not a bitset } *dst = bitset_container_create(); bool returnval = true; // expect a bitset if (*dst != NULL) { bitset_container_t *ourbitset = (bitset_container_t *)*dst; bitset_set_list(ourbitset->array, src_1->array, src_1->cardinality); ourbitset->cardinality = bitset_set_list_withcard(ourbitset->array, src_1->cardinality, src_2->array, src_2->cardinality); if (ourbitset->cardinality <= DEFAULT_MAX_SIZE) { // need to convert! *dst = array_container_from_bitset(ourbitset); bitset_container_free(ourbitset); returnval = false; // not going to be a bitset } } return returnval; }
/* Negation across a range of the container. * Compute the negation of src and write the result * to *dst. Returns true if the result is a bitset container * and false for an array container. *dst is not preallocated. */ bool array_container_negation_range(const array_container_t *src, const int range_start, const int range_end, void **dst) { /* close port of the Java implementation */ if (range_start >= range_end) { *dst = array_container_clone(src); return false; } int32_t start_index = binarySearch(src->array, src->cardinality, (uint16_t)range_start); if (start_index < 0) start_index = -start_index - 1; int32_t last_index = binarySearch(src->array, src->cardinality, (uint16_t)(range_end - 1)); if (last_index < 0) last_index = -last_index - 2; const int32_t current_values_in_range = last_index - start_index + 1; const int32_t span_to_be_flipped = range_end - range_start; const int32_t new_values_in_range = span_to_be_flipped - current_values_in_range; const int32_t cardinality_change = new_values_in_range - current_values_in_range; const int32_t new_cardinality = src->cardinality + cardinality_change; if (new_cardinality > DEFAULT_MAX_SIZE) { bitset_container_t *temp = bitset_container_from_array(src); bitset_flip_range(temp->array, (uint32_t)range_start, (uint32_t)range_end); temp->cardinality = new_cardinality; *dst = temp; return true; } array_container_t *arr = array_container_create_given_capacity(new_cardinality); *dst = (void *)arr; // copy stuff before the active area memcpy(arr->array, src->array, start_index * sizeof(uint16_t)); // work on the range int32_t out_pos = start_index, in_pos = start_index; int32_t val_in_range = range_start; for (; val_in_range < range_end && in_pos <= last_index; ++val_in_range) { if ((uint16_t)val_in_range != src->array[in_pos]) { arr->array[out_pos++] = (uint16_t)val_in_range; } else { ++in_pos; } } for (; val_in_range < range_end; ++val_in_range) arr->array[out_pos++] = (uint16_t)val_in_range; // content after the active range memcpy(arr->array + out_pos, src->array + (last_index + 1), (src->cardinality - (last_index + 1)) * sizeof(uint16_t)); arr->cardinality = new_cardinality; return false; }
bool run_bitset_container_andnot(const run_container_t *src_1, const bitset_container_t *src_2, void **dst) { // follows the Java implementation as of June 2016 int card = run_container_cardinality(src_1); if (card <= DEFAULT_MAX_SIZE) { // must be an array array_container_t *answer = array_container_create_given_capacity(card); answer->cardinality = 0; for (int32_t rlepos = 0; rlepos < src_1->n_runs; ++rlepos) { rle16_t rle = src_1->runs[rlepos]; for (int run_value = rle.value; run_value <= rle.value + rle.length; ++run_value) { if (!bitset_container_get(src_2, (uint16_t)run_value)) { answer->array[answer->cardinality++] = (uint16_t)run_value; } } } *dst = answer; return false; } else { // we guess it will be a bitset, though have to check guess when // done bitset_container_t *answer = bitset_container_clone(src_2); uint32_t last_pos = 0; for (int32_t rlepos = 0; rlepos < src_1->n_runs; ++rlepos) { rle16_t rle = src_1->runs[rlepos]; uint32_t start = rle.value; uint32_t end = start + rle.length + 1; bitset_reset_range(answer->array, last_pos, start); bitset_flip_range(answer->array, start, end); last_pos = end; } bitset_reset_range(answer->array, last_pos, (uint32_t)(1 << 16)); answer->cardinality = bitset_container_compute_cardinality(answer); if (answer->cardinality <= DEFAULT_MAX_SIZE) { *dst = array_container_from_bitset(answer); bitset_container_free(answer); return false; // not bitset } *dst = answer; return true; // bitset } }
bool bitset_bitset_container_intersection_inplace( bitset_container_t *src_1, const bitset_container_t *src_2, void **dst) { const int newCardinality = bitset_container_and_justcard(src_1, src_2); if (newCardinality > DEFAULT_MAX_SIZE) { *dst = src_1; bitset_container_and_nocard(src_1, src_2, src_1); ((bitset_container_t *)*dst)->cardinality = newCardinality; return true; // it is a bitset } *dst = array_container_create_given_capacity(newCardinality); if (*dst != NULL) { ((array_container_t *)*dst)->cardinality = newCardinality; bitset_extract_intersection_setbits_uint16( ((bitset_container_t *)src_1)->array, ((bitset_container_t *)src_2)->array, BITSET_CONTAINER_SIZE_IN_WORDS, ((array_container_t *)*dst)->array, 0); } return false; // not a bitset }
bool array_array_container_lazy_union(const array_container_t *src_1, const array_container_t *src_2, void **dst) { int totalCardinality = src_1->cardinality + src_2->cardinality; if (totalCardinality <= ARRAY_LAZY_LOWERBOUND) { *dst = array_container_create_given_capacity(totalCardinality); if (*dst != NULL) array_container_union(src_1, src_2, (array_container_t *)*dst); return false; // not a bitset } *dst = bitset_container_create(); bool returnval = true; // expect a bitset if (*dst != NULL) { bitset_container_t *ourbitset = (bitset_container_t *)*dst; bitset_set_list(ourbitset->array, src_1->array, src_1->cardinality); bitset_set_list(ourbitset->array, src_2->array, src_2->cardinality); ourbitset->cardinality = BITSET_UNKNOWN_CARDINALITY; } return returnval; }
/* Compute the intersection of src_1 and src_2 and write the result to * *dst. If the result is true then the result is a bitset_container_t * otherwise is a array_container_t. */ bool run_bitset_container_intersection(const run_container_t *src_1, const bitset_container_t *src_2, void **dst) { int32_t card = run_container_cardinality(src_1); if (card <= DEFAULT_MAX_SIZE) { // result can only be an array (assuming that we never make a // RunContainer) if (card > src_2->cardinality) { card = src_2->cardinality; } array_container_t *answer = array_container_create_given_capacity(card); *dst = answer; if (*dst == NULL) { return false; } for (int32_t rlepos = 0; rlepos < src_1->n_runs; ++rlepos) { rle16_t rle = src_1->runs[rlepos]; uint32_t endofrun = (uint32_t)rle.value + rle.length; for (uint32_t runValue = rle.value; runValue <= endofrun; ++runValue) { if (bitset_container_contains(src_2, runValue)) { answer->array[answer->cardinality++] = (uint16_t)runValue; } } } return false; } if (*dst == src_2) { // we attempt in-place bitset_container_t *answer = (bitset_container_t *)*dst; uint32_t start = 0; for (int32_t rlepos = 0; rlepos < src_1->n_runs; ++rlepos) { const rle16_t rle = src_1->runs[rlepos]; uint32_t end = rle.value; bitset_reset_range(src_2->array, start, end); start = end + rle.length + 1; } bitset_reset_range(src_2->array, start, UINT32_C(1) << 16); answer->cardinality = bitset_container_compute_cardinality(answer); if (src_2->cardinality > DEFAULT_MAX_SIZE) { return true; } else { array_container_t *newanswer = array_container_from_bitset(src_2); if (newanswer == NULL) { *dst = NULL; return false; } *dst = newanswer; return false; } } else { // no inplace // we expect the answer to be a bitmap (if we are lucky) bitset_container_t *answer = bitset_container_clone(src_2); *dst = answer; if (answer == NULL) { return true; } uint32_t start = 0; for (int32_t rlepos = 0; rlepos < src_1->n_runs; ++rlepos) { const rle16_t rle = src_1->runs[rlepos]; uint32_t end = rle.value; bitset_reset_range(answer->array, start, end); start = end + rle.length + 1; } bitset_reset_range(answer->array, start, UINT32_C(1) << 16); answer->cardinality = bitset_container_compute_cardinality(answer); if (answer->cardinality > DEFAULT_MAX_SIZE) { return true; } else { array_container_t *newanswer = array_container_from_bitset(answer); bitset_container_free(*dst); if (newanswer == NULL) { *dst = NULL; return false; } *dst = newanswer; return false; } } }
/* Create a new array. Return NULL in case of failure. */ array_container_t *array_container_create() { return array_container_create_given_capacity(DEFAULT_INIT_SIZE); }