Skip to content

Commit 89c04ba

Browse files
committed
Latest release
1 parent a8bcc1c commit 89c04ba

File tree

3 files changed

+371
-16
lines changed

3 files changed

+371
-16
lines changed

roaring.c

Lines changed: 213 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* auto-generated on Thu Mar 23 21:26:04 EDT 2017. Do not edit! */
1+
/* auto-generated on Fri Mar 24 10:26:41 EDT 2017. Do not edit! */
22
#include "roaring.h"
33
/* begin file src/array_util.c */
44
#include <assert.h>
@@ -712,8 +712,35 @@ int32_t intersect_skewed_uint16_cardinality(const uint16_t *small,
712712
return (int32_t)pos;
713713
}
714714

715+
bool intersect_skewed_uint16_nonempty(const uint16_t *small, size_t size_s,
716+
const uint16_t *large, size_t size_l) {
717+
size_t idx_l = 0, idx_s = 0;
718+
719+
if (0 == size_s) {
720+
return false;
721+
}
722+
723+
uint16_t val_l = large[idx_l], val_s = small[idx_s];
724+
725+
while (true) {
726+
if (val_l < val_s) {
727+
idx_l = advanceUntil(large, (int32_t)idx_l, (int32_t)size_l, val_s);
728+
if (idx_l == size_l) break;
729+
val_l = large[idx_l];
730+
} else if (val_s < val_l) {
731+
idx_s++;
732+
if (idx_s == size_s) break;
733+
val_s = small[idx_s];
734+
} else {
735+
return true;
736+
}
737+
}
738+
739+
return false;
740+
}
741+
715742
/**
716-
* Generic intersection function. Passes unit tests.
743+
* Generic intersection function.
717744
*/
718745
int32_t intersect_uint16(const uint16_t *A, const size_t lenA,
719746
const uint16_t *B, const size_t lenB, uint16_t *out) {
@@ -765,6 +792,32 @@ int32_t intersect_uint16_cardinality(const uint16_t *A, const size_t lenA,
765792
return answer; // NOTREACHED
766793
}
767794

795+
796+
bool intersect_uint16_nonempty(const uint16_t *A, const size_t lenA,
797+
const uint16_t *B, const size_t lenB) {
798+
if (lenA == 0 || lenB == 0) return 0;
799+
const uint16_t *endA = A + lenA;
800+
const uint16_t *endB = B + lenB;
801+
802+
while (1) {
803+
while (*A < *B) {
804+
SKIP_FIRST_COMPARE:
805+
if (++A == endA) return false;
806+
}
807+
while (*A > *B) {
808+
if (++B == endB) return false;
809+
}
810+
if (*A == *B) {
811+
return true;
812+
} else {
813+
goto SKIP_FIRST_COMPARE;
814+
}
815+
}
816+
return false; // NOTREACHED
817+
}
818+
819+
820+
768821
/**
769822
* Generic intersection function.
770823
*/
@@ -2895,6 +2948,23 @@ int array_container_intersection_cardinality(const array_container_t *array1,
28952948
}
28962949
}
28972950

2951+
bool array_container_intersect(const array_container_t *array1,
2952+
const array_container_t *array2) {
2953+
int32_t card_1 = array1->cardinality, card_2 = array2->cardinality;
2954+
const int threshold = 64; // subject to tuning
2955+
if (card_1 * threshold < card_2) {
2956+
return intersect_skewed_uint16_nonempty(
2957+
array1->array, card_1, array2->array, card_2);
2958+
} else if (card_2 * threshold < card_1) {
2959+
return intersect_skewed_uint16_nonempty(
2960+
array2->array, card_2, array1->array, card_1);
2961+
} else {
2962+
// we do not bother vectorizing
2963+
return intersect_uint16_nonempty(array1->array, card_1,
2964+
array2->array, card_2);
2965+
}
2966+
}
2967+
28982968
/* computes the intersection of array1 and array2 and write the result to
28992969
* array1.
29002970
* */
@@ -3136,6 +3206,8 @@ void bitset_container_set_all(bitset_container_t *bitset) {
31363206
bitset->cardinality = (1 << 16);
31373207
}
31383208

3209+
3210+
31393211
/* Create a new bitset. Return NULL in case of failure. */
31403212
bitset_container_t *bitset_container_create(void) {
31413213
bitset_container_t *bitset =
@@ -3226,8 +3298,16 @@ void bitset_container_set_range(bitset_container_t *bitset, uint32_t begin,
32263298
bitset_container_compute_cardinality(bitset); // could be smarter
32273299
}
32283300

3229-
//#define USEPOPCNT // when this is disabled
3230-
// bitset_container_compute_cardinality uses AVX to compute hamming weight
3301+
3302+
bool bitset_container_intersect(const bitset_container_t *src_1,
3303+
const bitset_container_t *src_2) {
3304+
// could vectorize, but this is probably already quite fast in practice
3305+
for (int i = 0; i < BITSET_CONTAINER_SIZE_IN_WORDS; i ++) {
3306+
if((src_1->array[i] & src_2->array[i]) != 0) return true;
3307+
}
3308+
return false;
3309+
}
3310+
32313311

32323312
#ifdef USEAVX
32333313
#ifndef WORDS_IN_AVX2_REG
@@ -4850,6 +4930,17 @@ int array_bitset_container_intersection_cardinality(
48504930
return newcard;
48514931
}
48524932

4933+
4934+
bool array_bitset_container_intersect(const array_container_t *src_1,
4935+
const bitset_container_t *src_2) {
4936+
const int32_t origcard = src_1->cardinality;
4937+
for (int i = 0; i < origcard; ++i) {
4938+
uint16_t key = src_1->array[i];
4939+
if(bitset_container_contains(src_2, key)) return true;
4940+
}
4941+
return false;
4942+
}
4943+
48534944
/* Compute the intersection of src_1 and src_2 and write the result to
48544945
* dst. It is allowed for dst to be equal to src_1. We assume that dst is a
48554946
* valid container. */
@@ -5033,6 +5124,53 @@ int run_bitset_container_intersection_cardinality(
50335124
return answer;
50345125
}
50355126

5127+
5128+
bool array_run_container_intersect(const array_container_t *src_1,
5129+
const run_container_t *src_2) {
5130+
if( run_container_is_full(src_2) ) {
5131+
return !array_container_empty(src_1);
5132+
}
5133+
if (src_2->n_runs == 0) {
5134+
return false;
5135+
}
5136+
int32_t rlepos = 0;
5137+
int32_t arraypos = 0;
5138+
rle16_t rle = src_2->runs[rlepos];
5139+
while (arraypos < src_1->cardinality) {
5140+
const uint16_t arrayval = src_1->array[arraypos];
5141+
while (rle.value + rle.length <
5142+
arrayval) { // this will frequently be false
5143+
++rlepos;
5144+
if (rlepos == src_2->n_runs) {
5145+
return false; // we are done
5146+
}
5147+
rle = src_2->runs[rlepos];
5148+
}
5149+
if (rle.value > arrayval) {
5150+
arraypos = advanceUntil(src_1->array, arraypos, src_1->cardinality,
5151+
rle.value);
5152+
} else {
5153+
return true;
5154+
arraypos++;
5155+
}
5156+
}
5157+
return false;
5158+
}
5159+
5160+
/* Compute the intersection between src_1 and src_2
5161+
**/
5162+
bool run_bitset_container_intersect(const run_container_t *src_1,
5163+
const bitset_container_t *src_2) {
5164+
if( run_container_is_full(src_1) ) {
5165+
return !bitset_container_empty(src_2);
5166+
}
5167+
for (int32_t rlepos = 0; rlepos < src_1->n_runs; ++rlepos) {
5168+
rle16_t rle = src_1->runs[rlepos];
5169+
if(!bitset_lenrange_empty(src_2->array, rle.value,rle.length)) return true;
5170+
}
5171+
return false;
5172+
}
5173+
50365174
/*
50375175
* Compute the intersection between src_1 and src_2 and write the result
50385176
* to *dst. If the return function is true, the result is a bitset_container_t
@@ -6521,10 +6659,10 @@ int run_container_intersection_cardinality(const run_container_t *src_1,
65216659
const bool if2 = run_container_is_full(src_2);
65226660
if (if1 || if2) {
65236661
if (if1) {
6524-
run_container_cardinality(src_2);
6662+
return run_container_cardinality(src_2);
65256663
}
65266664
if (if2) {
6527-
run_container_cardinality(src_1);
6665+
return run_container_cardinality(src_1);
65286666
}
65296667
}
65306668
int answer = 0;
@@ -6584,6 +6722,45 @@ int run_container_intersection_cardinality(const run_container_t *src_1,
65846722
return answer;
65856723
}
65866724

6725+
bool run_container_intersect(const run_container_t *src_1,
6726+
const run_container_t *src_2) {
6727+
const bool if1 = run_container_is_full(src_1);
6728+
const bool if2 = run_container_is_full(src_2);
6729+
if (if1 || if2) {
6730+
if (if1) {
6731+
return !run_container_empty(src_2);
6732+
}
6733+
if (if2) {
6734+
return !run_container_empty(src_1);
6735+
}
6736+
}
6737+
int32_t rlepos = 0;
6738+
int32_t xrlepos = 0;
6739+
int32_t start = src_1->runs[rlepos].value;
6740+
int32_t end = start + src_1->runs[rlepos].length + 1;
6741+
int32_t xstart = src_2->runs[xrlepos].value;
6742+
int32_t xend = xstart + src_2->runs[xrlepos].length + 1;
6743+
while ((rlepos < src_1->n_runs) && (xrlepos < src_2->n_runs)) {
6744+
if (end <= xstart) {
6745+
++rlepos;
6746+
if (rlepos < src_1->n_runs) {
6747+
start = src_1->runs[rlepos].value;
6748+
end = start + src_1->runs[rlepos].length + 1;
6749+
}
6750+
} else if (xend <= start) {
6751+
++xrlepos;
6752+
if (xrlepos < src_2->n_runs) {
6753+
xstart = src_2->runs[xrlepos].value;
6754+
xend = xstart + src_2->runs[xrlepos].length + 1;
6755+
}
6756+
} else { // they overlap
6757+
return true;
6758+
}
6759+
}
6760+
return false;
6761+
}
6762+
6763+
65876764
/* Compute the difference of src_1 and src_2 and write the result to
65886765
* dst. It is assumed that dst is distinct from both src_1 and src_2. */
65896766
void run_container_andnot(const run_container_t *src_1,
@@ -8903,6 +9080,36 @@ bool roaring_bitmap_select(const roaring_bitmap_t *bm, uint32_t rank,
89039080
return false;
89049081
}
89059082

9083+
bool roaring_bitmap_intersect(const roaring_bitmap_t *x1,
9084+
const roaring_bitmap_t *x2) {
9085+
const int length1 = x1->high_low_container.size,
9086+
length2 = x2->high_low_container.size;
9087+
uint64_t answer = 0;
9088+
int pos1 = 0, pos2 = 0;
9089+
9090+
while (pos1 < length1 && pos2 < length2) {
9091+
const uint16_t s1 = ra_get_key_at_index(& x1->high_low_container, pos1);
9092+
const uint16_t s2 = ra_get_key_at_index(& x2->high_low_container, pos2);
9093+
9094+
if (s1 == s2) {
9095+
uint8_t container_type_1, container_type_2;
9096+
void *c1 = ra_get_container_at_index(& x1->high_low_container, pos1,
9097+
&container_type_1);
9098+
void *c2 = ra_get_container_at_index(& x2->high_low_container, pos2,
9099+
&container_type_2);
9100+
if( container_intersect(c1, container_type_1, c2, container_type_2) ) return true;
9101+
++pos1;
9102+
++pos2;
9103+
} else if (s1 < s2) { // s1 < s2
9104+
pos1 = ra_advance_until(& x1->high_low_container, s2, pos1);
9105+
} else { // s1 > s2
9106+
pos2 = ra_advance_until(& x2->high_low_container, s1, pos2);
9107+
}
9108+
}
9109+
return answer;
9110+
}
9111+
9112+
89069113
uint64_t roaring_bitmap_and_cardinality(const roaring_bitmap_t *x1,
89079114
const roaring_bitmap_t *x2) {
89089115
const int length1 = x1->high_low_container.size,

0 commit comments

Comments
 (0)