|
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! */ |
2 | 2 | #include "roaring.h" |
3 | 3 | /* begin file src/array_util.c */ |
4 | 4 | #include <assert.h> |
@@ -712,8 +712,35 @@ int32_t intersect_skewed_uint16_cardinality(const uint16_t *small, |
712 | 712 | return (int32_t)pos; |
713 | 713 | } |
714 | 714 |
|
| 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 | + |
715 | 742 | /** |
716 | | - * Generic intersection function. Passes unit tests. |
| 743 | + * Generic intersection function. |
717 | 744 | */ |
718 | 745 | int32_t intersect_uint16(const uint16_t *A, const size_t lenA, |
719 | 746 | 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, |
765 | 792 | return answer; // NOTREACHED |
766 | 793 | } |
767 | 794 |
|
| 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 | + |
768 | 821 | /** |
769 | 822 | * Generic intersection function. |
770 | 823 | */ |
@@ -2895,6 +2948,23 @@ int array_container_intersection_cardinality(const array_container_t *array1, |
2895 | 2948 | } |
2896 | 2949 | } |
2897 | 2950 |
|
| 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 | + |
2898 | 2968 | /* computes the intersection of array1 and array2 and write the result to |
2899 | 2969 | * array1. |
2900 | 2970 | * */ |
@@ -3136,6 +3206,8 @@ void bitset_container_set_all(bitset_container_t *bitset) { |
3136 | 3206 | bitset->cardinality = (1 << 16); |
3137 | 3207 | } |
3138 | 3208 |
|
| 3209 | + |
| 3210 | + |
3139 | 3211 | /* Create a new bitset. Return NULL in case of failure. */ |
3140 | 3212 | bitset_container_t *bitset_container_create(void) { |
3141 | 3213 | bitset_container_t *bitset = |
@@ -3226,8 +3298,16 @@ void bitset_container_set_range(bitset_container_t *bitset, uint32_t begin, |
3226 | 3298 | bitset_container_compute_cardinality(bitset); // could be smarter |
3227 | 3299 | } |
3228 | 3300 |
|
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 | + |
3231 | 3311 |
|
3232 | 3312 | #ifdef USEAVX |
3233 | 3313 | #ifndef WORDS_IN_AVX2_REG |
@@ -4850,6 +4930,17 @@ int array_bitset_container_intersection_cardinality( |
4850 | 4930 | return newcard; |
4851 | 4931 | } |
4852 | 4932 |
|
| 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 | + |
4853 | 4944 | /* Compute the intersection of src_1 and src_2 and write the result to |
4854 | 4945 | * dst. It is allowed for dst to be equal to src_1. We assume that dst is a |
4855 | 4946 | * valid container. */ |
@@ -5033,6 +5124,53 @@ int run_bitset_container_intersection_cardinality( |
5033 | 5124 | return answer; |
5034 | 5125 | } |
5035 | 5126 |
|
| 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 | + |
5036 | 5174 | /* |
5037 | 5175 | * Compute the intersection between src_1 and src_2 and write the result |
5038 | 5176 | * 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, |
6521 | 6659 | const bool if2 = run_container_is_full(src_2); |
6522 | 6660 | if (if1 || if2) { |
6523 | 6661 | if (if1) { |
6524 | | - run_container_cardinality(src_2); |
| 6662 | + return run_container_cardinality(src_2); |
6525 | 6663 | } |
6526 | 6664 | if (if2) { |
6527 | | - run_container_cardinality(src_1); |
| 6665 | + return run_container_cardinality(src_1); |
6528 | 6666 | } |
6529 | 6667 | } |
6530 | 6668 | int answer = 0; |
@@ -6584,6 +6722,45 @@ int run_container_intersection_cardinality(const run_container_t *src_1, |
6584 | 6722 | return answer; |
6585 | 6723 | } |
6586 | 6724 |
|
| 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 | + |
6587 | 6764 | /* Compute the difference of src_1 and src_2 and write the result to |
6588 | 6765 | * dst. It is assumed that dst is distinct from both src_1 and src_2. */ |
6589 | 6766 | 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, |
8903 | 9080 | return false; |
8904 | 9081 | } |
8905 | 9082 |
|
| 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 | + |
8906 | 9113 | uint64_t roaring_bitmap_and_cardinality(const roaring_bitmap_t *x1, |
8907 | 9114 | const roaring_bitmap_t *x2) { |
8908 | 9115 | const int length1 = x1->high_low_container.size, |
|
0 commit comments