/* Compute the intersection of src_1 and src_2 and write the result to * dst. It is allowed for dst to be equal to src_1. We assume that dst is a * valid container. */ void array_run_container_intersection(const array_container_t *src_1, const run_container_t *src_2, array_container_t *dst) { if (dst->capacity < src_1->cardinality) array_container_grow(dst, src_1->cardinality, INT32_MAX, false); if (src_2->n_runs == 0) { return; } int32_t rlepos = 0; int32_t arraypos = 0; rle16_t rle = src_2->runs[rlepos]; int32_t newcard = 0; while (arraypos < src_1->cardinality) { const uint16_t arrayval = src_1->array[arraypos]; while (rle.value + rle.length < arrayval) { // this will frequently be false ++rlepos; if (rlepos == src_2->n_runs) { dst->cardinality = newcard; return; // we are done } rle = src_2->runs[rlepos]; } if (rle.value > arrayval) { arraypos = advanceUntil(src_1->array, arraypos, src_1->cardinality, rle.value); } else { dst->array[newcard] = arrayval; newcard++; arraypos++; } } dst->cardinality = newcard; }
static int run_array_array_subtract(const run_container_t *r, const array_container_t *a_in, array_container_t *a_out) { int out_card = 0; int32_t in_array_pos = -1; // since advanceUntil always assumes we start the search AFTER this for (int rlepos = 0; rlepos < r->n_runs; rlepos++) { int32_t start = r->runs[rlepos].value; int32_t end = start + r->runs[rlepos].length + 1; in_array_pos = advanceUntil(a_in->array, in_array_pos, a_in->cardinality, (uint16_t)start); if (in_array_pos >= a_in->cardinality) { // run has no items subtracted for (int32_t i = start; i < end; ++i) a_out->array[out_card++] = (uint16_t)i; } else { uint16_t next_nonincluded = a_in->array[in_array_pos]; if (next_nonincluded >= end) { // another case when run goes unaltered for (int32_t i = start; i < end; ++i) a_out->array[out_card++] = (uint16_t)i; in_array_pos--; // ensure we see this item again if necessary } else { for (int32_t i = start; i < end; ++i) if (i != next_nonincluded) a_out->array[out_card++] = (uint16_t)i; else // 0 should ensure we don't match next_nonincluded = (in_array_pos + 1 >= a_in->cardinality) ? 0 : a_in->array[++in_array_pos]; in_array_pos--; // see again } } } return out_card; }