/var/local/thirdparty/installed/include/roaring/array_util.h
Line | Count | Source (jump to first uncovered line) |
1 | | #ifndef ARRAY_UTIL_H |
2 | | #define ARRAY_UTIL_H |
3 | | |
4 | | #include <stddef.h> // for size_t |
5 | | #include <stdint.h> |
6 | | |
7 | | #include <roaring/portability.h> |
8 | | |
9 | | #if CROARING_IS_X64 |
10 | | #ifndef CROARING_COMPILER_SUPPORTS_AVX512 |
11 | | #error "CROARING_COMPILER_SUPPORTS_AVX512 needs to be defined." |
12 | | #endif // CROARING_COMPILER_SUPPORTS_AVX512 |
13 | | #endif |
14 | | |
15 | | #ifdef __cplusplus |
16 | | extern "C" { namespace roaring { namespace internal { |
17 | | #endif |
18 | | |
19 | | /* |
20 | | * Good old binary search. |
21 | | * Assumes that array is sorted, has logarithmic complexity. |
22 | | * if the result is x, then: |
23 | | * if ( x>0 ) you have array[x] = ikey |
24 | | * if ( x<0 ) then inserting ikey at position -x-1 in array (insuring that array[-x-1]=ikey) |
25 | | * keys the array sorted. |
26 | | */ |
27 | | inline int32_t binarySearch(const uint16_t *array, int32_t lenarray, |
28 | 0 | uint16_t ikey) { |
29 | 0 | int32_t low = 0; |
30 | 0 | int32_t high = lenarray - 1; |
31 | 0 | while (low <= high) { |
32 | 0 | int32_t middleIndex = (low + high) >> 1; |
33 | 0 | uint16_t middleValue = array[middleIndex]; |
34 | 0 | if (middleValue < ikey) { |
35 | 0 | low = middleIndex + 1; |
36 | 0 | } else if (middleValue > ikey) { |
37 | 0 | high = middleIndex - 1; |
38 | 0 | } else { |
39 | 0 | return middleIndex; |
40 | 0 | } |
41 | 0 | } |
42 | 0 | return -(low + 1); |
43 | 0 | } |
44 | | |
45 | | /** |
46 | | * Galloping search |
47 | | * Assumes that array is sorted, has logarithmic complexity. |
48 | | * if the result is x, then if x = length, you have that all values in array between pos and length |
49 | | * are smaller than min. |
50 | | * otherwise returns the first index x such that array[x] >= min. |
51 | | */ |
52 | | static inline int32_t advanceUntil(const uint16_t *array, int32_t pos, |
53 | 0 | int32_t length, uint16_t min) { |
54 | 0 | int32_t lower = pos + 1; |
55 | 0 |
|
56 | 0 | if ((lower >= length) || (array[lower] >= min)) { |
57 | 0 | return lower; |
58 | 0 | } |
59 | 0 |
|
60 | 0 | int32_t spansize = 1; |
61 | 0 |
|
62 | 0 | while ((lower + spansize < length) && (array[lower + spansize] < min)) { |
63 | 0 | spansize <<= 1; |
64 | 0 | } |
65 | 0 | int32_t upper = (lower + spansize < length) ? lower + spansize : length - 1; |
66 | 0 |
|
67 | 0 | if (array[upper] == min) { |
68 | 0 | return upper; |
69 | 0 | } |
70 | 0 | if (array[upper] < min) { |
71 | 0 | // means |
72 | 0 | // array |
73 | 0 | // has no |
74 | 0 | // item |
75 | 0 | // >= min |
76 | 0 | // pos = array.length; |
77 | 0 | return length; |
78 | 0 | } |
79 | 0 |
|
80 | 0 | // we know that the next-smallest span was too small |
81 | 0 | lower += (spansize >> 1); |
82 | 0 |
|
83 | 0 | int32_t mid = 0; |
84 | 0 | while (lower + 1 != upper) { |
85 | 0 | mid = (lower + upper) >> 1; |
86 | 0 | if (array[mid] == min) { |
87 | 0 | return mid; |
88 | 0 | } else if (array[mid] < min) { |
89 | 0 | lower = mid; |
90 | 0 | } else { |
91 | 0 | upper = mid; |
92 | 0 | } |
93 | 0 | } |
94 | 0 | return upper; |
95 | 0 | } Unexecuted instantiation: bkd_writer.cpp:_ZN7roaring8internalL12advanceUntilEPKtiit Unexecuted instantiation: bkd_reader.cpp:_ZN7roaring8internalL12advanceUntilEPKtiit Unexecuted instantiation: packed_index_tree.cpp:_ZN7roaring8internalL12advanceUntilEPKtiit Unexecuted instantiation: index_tree.cpp:_ZN7roaring8internalL12advanceUntilEPKtiit Unexecuted instantiation: legacy_index_tree.cpp:_ZN7roaring8internalL12advanceUntilEPKtiit Unexecuted instantiation: docids_writer.cpp:_ZN7roaring8internalL12advanceUntilEPKtiit Unexecuted instantiation: IndexWriter.cpp:_ZN7roaring8internalL12advanceUntilEPKtiit |
96 | | |
97 | | /** |
98 | | * Returns number of elements which are less than ikey. |
99 | | * Array elements must be unique and sorted. |
100 | | */ |
101 | | static inline int32_t count_less(const uint16_t *array, int32_t lenarray, |
102 | 0 | uint16_t ikey) { |
103 | 0 | if (lenarray == 0) return 0; |
104 | 0 | int32_t pos = binarySearch(array, lenarray, ikey); |
105 | 0 | return pos >= 0 ? pos : -(pos+1); |
106 | 0 | } Unexecuted instantiation: bkd_writer.cpp:_ZN7roaring8internalL10count_lessEPKtit Unexecuted instantiation: bkd_reader.cpp:_ZN7roaring8internalL10count_lessEPKtit Unexecuted instantiation: packed_index_tree.cpp:_ZN7roaring8internalL10count_lessEPKtit Unexecuted instantiation: index_tree.cpp:_ZN7roaring8internalL10count_lessEPKtit Unexecuted instantiation: legacy_index_tree.cpp:_ZN7roaring8internalL10count_lessEPKtit Unexecuted instantiation: docids_writer.cpp:_ZN7roaring8internalL10count_lessEPKtit Unexecuted instantiation: IndexWriter.cpp:_ZN7roaring8internalL10count_lessEPKtit |
107 | | |
108 | | /** |
109 | | * Returns number of elements which are greater than ikey. |
110 | | * Array elements must be unique and sorted. |
111 | | */ |
112 | | static inline int32_t count_greater(const uint16_t *array, int32_t lenarray, |
113 | 0 | uint16_t ikey) { |
114 | 0 | if (lenarray == 0) return 0; |
115 | 0 | int32_t pos = binarySearch(array, lenarray, ikey); |
116 | 0 | if (pos >= 0) { |
117 | 0 | return lenarray - (pos+1); |
118 | 0 | } else { |
119 | 0 | return lenarray - (-pos-1); |
120 | 0 | } |
121 | 0 | } Unexecuted instantiation: bkd_writer.cpp:_ZN7roaring8internalL13count_greaterEPKtit Unexecuted instantiation: bkd_reader.cpp:_ZN7roaring8internalL13count_greaterEPKtit Unexecuted instantiation: packed_index_tree.cpp:_ZN7roaring8internalL13count_greaterEPKtit Unexecuted instantiation: index_tree.cpp:_ZN7roaring8internalL13count_greaterEPKtit Unexecuted instantiation: legacy_index_tree.cpp:_ZN7roaring8internalL13count_greaterEPKtit Unexecuted instantiation: docids_writer.cpp:_ZN7roaring8internalL13count_greaterEPKtit Unexecuted instantiation: IndexWriter.cpp:_ZN7roaring8internalL13count_greaterEPKtit |
122 | | |
123 | | /** |
124 | | * From Schlegel et al., Fast Sorted-Set Intersection using SIMD Instructions |
125 | | * Optimized by D. Lemire on May 3rd 2013 |
126 | | * |
127 | | * C should have capacity greater than the minimum of s_1 and s_b + 8 |
128 | | * where 8 is sizeof(__m128i)/sizeof(uint16_t). |
129 | | */ |
130 | | int32_t intersect_vector16(const uint16_t *__restrict__ A, size_t s_a, |
131 | | const uint16_t *__restrict__ B, size_t s_b, |
132 | | uint16_t *C); |
133 | | |
134 | | int32_t intersect_vector16_inplace(uint16_t *__restrict__ A, size_t s_a, |
135 | | const uint16_t *__restrict__ B, size_t s_b); |
136 | | |
137 | | /** |
138 | | * Take an array container and write it out to a 32-bit array, using base |
139 | | * as the offset. |
140 | | */ |
141 | | int array_container_to_uint32_array_vector16(void *vout, const uint16_t* array, size_t cardinality, |
142 | | uint32_t base); |
143 | | #if CROARING_COMPILER_SUPPORTS_AVX512 |
144 | | int avx512_array_container_to_uint32_array(void *vout, const uint16_t* array, size_t cardinality, |
145 | | uint32_t base); |
146 | | #endif |
147 | | /** |
148 | | * Compute the cardinality of the intersection using SSE4 instructions |
149 | | */ |
150 | | int32_t intersect_vector16_cardinality(const uint16_t *__restrict__ A, |
151 | | size_t s_a, |
152 | | const uint16_t *__restrict__ B, |
153 | | size_t s_b); |
154 | | |
155 | | /* Computes the intersection between one small and one large set of uint16_t. |
156 | | * Stores the result into buffer and return the number of elements. */ |
157 | | int32_t intersect_skewed_uint16(const uint16_t *smallarray, size_t size_s, |
158 | | const uint16_t *largearray, size_t size_l, |
159 | | uint16_t *buffer); |
160 | | |
161 | | /* Computes the size of the intersection between one small and one large set of |
162 | | * uint16_t. */ |
163 | | int32_t intersect_skewed_uint16_cardinality(const uint16_t *smallarray, |
164 | | size_t size_s, |
165 | | const uint16_t *largearray, |
166 | | size_t size_l); |
167 | | |
168 | | |
169 | | /* Check whether the size of the intersection between one small and one large set of uint16_t is non-zero. */ |
170 | | bool intersect_skewed_uint16_nonempty(const uint16_t *smallarray, size_t size_s, |
171 | | const uint16_t *largearray, size_t size_l); |
172 | | /** |
173 | | * Generic intersection function. |
174 | | */ |
175 | | int32_t intersect_uint16(const uint16_t *A, const size_t lenA, |
176 | | const uint16_t *B, const size_t lenB, uint16_t *out); |
177 | | /** |
178 | | * Compute the size of the intersection (generic). |
179 | | */ |
180 | | int32_t intersect_uint16_cardinality(const uint16_t *A, const size_t lenA, |
181 | | const uint16_t *B, const size_t lenB); |
182 | | |
183 | | /** |
184 | | * Checking whether the size of the intersection is non-zero. |
185 | | */ |
186 | | bool intersect_uint16_nonempty(const uint16_t *A, const size_t lenA, |
187 | | const uint16_t *B, const size_t lenB); |
188 | | /** |
189 | | * Generic union function. |
190 | | */ |
191 | | size_t union_uint16(const uint16_t *set_1, size_t size_1, const uint16_t *set_2, |
192 | | size_t size_2, uint16_t *buffer); |
193 | | |
194 | | /** |
195 | | * Generic XOR function. |
196 | | */ |
197 | | int32_t xor_uint16(const uint16_t *array_1, int32_t card_1, |
198 | | const uint16_t *array_2, int32_t card_2, uint16_t *out); |
199 | | |
200 | | /** |
201 | | * Generic difference function (ANDNOT). |
202 | | */ |
203 | | int difference_uint16(const uint16_t *a1, int length1, const uint16_t *a2, |
204 | | int length2, uint16_t *a_out); |
205 | | |
206 | | /** |
207 | | * Generic intersection function. |
208 | | */ |
209 | | size_t intersection_uint32(const uint32_t *A, const size_t lenA, |
210 | | const uint32_t *B, const size_t lenB, uint32_t *out); |
211 | | |
212 | | /** |
213 | | * Generic intersection function, returns just the cardinality. |
214 | | */ |
215 | | size_t intersection_uint32_card(const uint32_t *A, const size_t lenA, |
216 | | const uint32_t *B, const size_t lenB); |
217 | | |
218 | | /** |
219 | | * Generic union function. |
220 | | */ |
221 | | size_t union_uint32(const uint32_t *set_1, size_t size_1, const uint32_t *set_2, |
222 | | size_t size_2, uint32_t *buffer); |
223 | | |
224 | | /** |
225 | | * A fast SSE-based union function. |
226 | | */ |
227 | | uint32_t union_vector16(const uint16_t *__restrict__ set_1, uint32_t size_1, |
228 | | const uint16_t *__restrict__ set_2, uint32_t size_2, |
229 | | uint16_t *__restrict__ buffer); |
230 | | /** |
231 | | * A fast SSE-based XOR function. |
232 | | */ |
233 | | uint32_t xor_vector16(const uint16_t *__restrict__ array1, uint32_t length1, |
234 | | const uint16_t *__restrict__ array2, uint32_t length2, |
235 | | uint16_t *__restrict__ output); |
236 | | |
237 | | /** |
238 | | * A fast SSE-based difference function. |
239 | | */ |
240 | | int32_t difference_vector16(const uint16_t *__restrict__ A, size_t s_a, |
241 | | const uint16_t *__restrict__ B, size_t s_b, |
242 | | uint16_t *C); |
243 | | |
244 | | /** |
245 | | * Generic union function, returns just the cardinality. |
246 | | */ |
247 | | size_t union_uint32_card(const uint32_t *set_1, size_t size_1, |
248 | | const uint32_t *set_2, size_t size_2); |
249 | | |
250 | | /** |
251 | | * combines union_uint16 and union_vector16 optimally |
252 | | */ |
253 | | size_t fast_union_uint16(const uint16_t *set_1, size_t size_1, const uint16_t *set_2, |
254 | | size_t size_2, uint16_t *buffer); |
255 | | |
256 | | |
257 | | bool memequals(const void *s1, const void *s2, size_t n); |
258 | | |
259 | | #ifdef __cplusplus |
260 | | } } } // extern "C" { namespace roaring { namespace internal { |
261 | | #endif |
262 | | |
263 | | #endif |